Example #1
0
    def test_amplitude_damping_channel(self):
        psi0 = State(np.zeros((2, 2)))
        psi0[0, 0] = 1
        spontaneous_emission = quantum_channels.AmplitudeDampingChannel()
        for i in range(200):
            psi0 = spontaneous_emission.channel(psi0, .1)
        self.assertTrue(np.allclose(psi0, np.array([[0, 0], [0, 1]])))
        psi0 = State(np.zeros((2, 2)))
        psi0[0, 0] = 1
        psi0 = spontaneous_emission.evolve(psi0, 20)
        self.assertTrue(np.allclose(psi0, np.array([[0, 0], [0, 1]])))
        psi0 = State(np.zeros((2, 2)), IS_subspace=True, graph=line_graph(1))
        psi0[0, 0] = 1
        spontaneous_emission = quantum_channels.AmplitudeDampingChannel(
            IS_subspace=True, graph=line_graph(1), rates=(2, ))
        psi0 = spontaneous_emission.evolve(psi0, 20)
        self.assertTrue(np.allclose(psi0, np.array([[0, 0], [0, 1]])))

        psi0 = State(np.zeros((8, 8)),
                     IS_subspace=True,
                     code=rydberg,
                     graph=line_graph(2))
        psi0[3, 3] = 1
        spontaneous_emission = quantum_channels.AmplitudeDampingChannel(
            IS_subspace=True,
            graph=line_graph(2),
            rates=(2, ),
            code=rydberg,
            transition=(1, 2))
        psi0 = spontaneous_emission.evolve(psi0, 1)
        print(psi0)
Example #2
0
    def test_trotterize_noisy(self):
        # Noisy simulations
        simulation = adiabatic_simulation(line_graph(2),
                                          IS_subspace=False,
                                          noisy=True,
                                          trotterize=True)
        res_trotterize = simulation.performance_vs_total_time(
            np.arange(1, 4, 1) * 10,
            metric='optimum_overlap',
            schedule=lambda t, tf: simulation.linear_schedule(
                t, tf, coefficients=[10, 10]),
            plot=False,
            verbose=True,
            method='trotterize')
        simulation = adiabatic_simulation(line_graph(2),
                                          IS_subspace=False,
                                          noisy=True,
                                          trotterize=False)

        res_odeint = simulation.performance_vs_total_time(
            np.arange(1, 4, 1) * 10,
            metric='optimum_overlap',
            schedule=lambda t, tf: simulation.linear_schedule(
                t, tf, coefficients=[10, 10]),
            plot=False,
            verbose=True,
            method='odeint')

        self.assertTrue(
            np.allclose(res_trotterize[0]['trotterize']['optimum_overlap'],
                        res_odeint[0]['odeint']['optimum_overlap'],
                        atol=1e-2))
Example #3
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()
Example #4
0
def ARvstime_EIT(tf=10, graph=None, mis=None, show_graph=False, n=3):
    schedule = lambda t, tf: [[t / tf, (tf - t) / tf, 1], [1]]
    if graph is None:
        graph, mis = line_graph(n=n)
    graph = Graph(graph)
    if show_graph:
        nx.draw(graph)
        plt.show()
    rabi1 = 3
    rabi2 = 3
    # Generate the driving
    laser1 = hamiltonian.HamiltonianDriver(transition=(0, 1),
                                           energy=rabi1,
                                           code=rydberg,
                                           IS_subspace=True,
                                           graph=graph)
    laser2 = hamiltonian.HamiltonianDriver(transition=(1, 2),
                                           energy=rabi2,
                                           code=rydberg,
                                           IS_subspace=True,
                                           graph=graph)
    rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph,
                                                          code=rydberg,
                                                          detuning=1,
                                                          energy=0,
                                                          IS_subspace=True)
    # Initialize spontaneous emission
    spontaneous_emission_rate = 1
    spontaneous_emission = lindblad_operators.SpontaneousEmission(
        transition=(1, 2),
        rate=spontaneous_emission_rate,
        code=rydberg,
        IS_subspace=True,
        graph=graph)

    # Initialize master equation
    master_equation = LindbladMasterEquation(
        hamiltonians=[laser2, laser1], jump_operators=[spontaneous_emission])
    # Begin with all qubits in the ground codes
    psi = np.zeros((rydberg_hamiltonian_cost.hamiltonian.shape[0], 1),
                   dtype=np.complex128)
    psi[-1, -1] = 1
    psi = tools.outer_product(psi, psi)
    # Generate annealing schedule
    results = master_equation.run_ode_solver(
        psi, 0, tf, num_from_time(tf), schedule=lambda t: schedule(t, tf))
    cost_function = [
        rydberg_hamiltonian_cost.cost_function(results[i], is_ket=False) / mis
        for i in range(results.shape[0])
    ]
    print(cost_function[-1])
    plt.scatter(np.linspace(0, tf, num_from_time(tf)),
                cost_function,
                c='teal',
                label='approximation ratio')
    plt.legend()
    plt.xlabel(r'Approximation ratio')
    plt.ylabel(r'Time $t$')
    plt.show()
Example #5
0
def p_check_compare(tau, eps, L=12, h=1, verbose=False):
    if verbose:
        print('starting ham')
    disorder = (np.random.random(size=L) - 1 / 2) * h
    #disorder = np.array([0.848539, -0.038314, -0.170679, 0.384688, 0.00254869, 0.877209, -0.523275, -0.628435])/2
    #np.set_printoptions(threshold=np.inf)
    #print(repr(disorder))
    graph = line_graph(L)
    Heis = ham.HamiltonianHeisenberg(graph,
                                     energies=(1 / 4, 1 / 4),
                                     subspace='all')

    def matvec_disorder(x):
        if len(x.shape) == 2:
            return matvec_heisenberg(Heis, disorder, State(x))
        else:
            return matvec_heisenberg(Heis, disorder,
                                     State(np.expand_dims(x, axis=-1)))

    disorder_heis = sp.sparse.linalg.LinearOperator((2**L, 2**L),
                                                    matvec=matvec_disorder)
    dill.dump(disorder_heis,
              open('heisenberg_linear_op_' + str(graph.n) + '.pickle', 'wb'))
    if verbose:
        print('done with ham')
    # initial state:
    v0 = State(np.zeros((2**L, 1)))
    v0[0] = 1
    p_checks = np.arange(1, 11)
    #nu_max = 7
    #if verbose:
    #    print('start kryl')
    #nmatvec, runtime, expk = krylov(disorder_heis, v0, tau, eps, p_check, nu_max, return_cost=True)
    #print('done kryl, {} matvec, {} s'.format(nmatvec, runtime))
    tols = [1e-2, 1e-4, 1e-6]
    matvecs = np.zeros((len(tols), len(p_checks)))
    for (t, tol) in enumerate(tols):
        for (p, p_check) in enumerate(p_checks):
            if verbose:
                print('start cheb')
            nmatvec, runtime, expc = chebyshev(disorder_heis,
                                               v0,
                                               tau,
                                               tol,
                                               p_check,
                                               return_cost=True)
            matvecs[t, p] = nmatvec
            print('done cheb, {} matvec, {} s, {}'.format(
                nmatvec, runtime, p_check))
            print(matvecs)
Example #6
0
def rate_vs_eigenenergy(times, graph=line_graph(n=2), which='S'):
    """For REIT, compute the total leakage from the ground state to a given state. Plot the total leakage versus
    the final eigenenergy"""
    bad = np.arange(0, 2**graph.n, 1)
    if which == 'S':
        index = 0
    elif which == 'L':
        index = -1
    else:
        index = which
    bad = np.delete(bad, index)
    full_rates = np.zeros(len(bad))

    # Good is a list of good eigenvalues
    # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good'
    def schedule(t, tf):
        phi = (tf - t) / tf * np.pi / 2
        x.energies = (np.sin(phi)**2, )

    x = hamiltonian.HamiltonianDriver(graph=graph,
                                      IS_subspace=False,
                                      energies=(1, ))
    zz = hamiltonian.HamiltonianMaxCut(graph,
                                       cost_function=False,
                                       energies=(1 / 2, ))
    #dissipation = lindblad_operators.SpontaneousEmission(graph=graph, rates=(1,))
    eq = SchrodingerEquation(hamiltonians=[x, zz])

    def compute_rate():
        # Construct the first order transition matrix
        energies, states = eq.eig(k='all')
        rates = np.zeros(len(bad))
        for j in range(graph.n):
            for i in range(len(bad)):
                rates[i] = rates[i] + (np.abs(
                    states[i].conj() @ qubit.left_multiply(
                        State(states[index].T), [j], qubit.Z))**2)[0, 0]
        # Select the relevant rates from 'good' to 'bad'
        print(rates)
        return rates

    for i in range(len(times)):
        print(times[i])
        schedule(times[i], 1)
        full_rates = full_rates + compute_rate()
        eigval, eigvec = eq.eig(k='all')
    return full_rates, eigval
def run(times, n=2, approximate=False):
    graph = line_graph(n)
    simulation = adiabatic_simulation(graph, approximate=approximate)

    def experiment_rydberg_MIS_schedule(t, tf, coefficients=None):
        if coefficients is None:
            coefficients = [1, 1, 1]
        if len(simulation.hamiltonian) == 2:
            for i in range(len(simulation.hamiltonian)):
                if i == 0:
                    # We don't want to update normal detunings
                    simulation.hamiltonian[i].energies = [
                        coefficients[0] * np.sin(np.pi * t / tf)**2
                    ]
                if i == 1:
                    simulation.hamiltonian[i].energies = [
                        coefficients[1] * (2 * t / tf - 1)
                    ]
        else:
            for i in range(len(simulation.hamiltonian)):
                if i == 0:
                    # We don't want to update normal detunings
                    simulation.hamiltonian[i].energies = [
                        coefficients[0] * np.sin(np.pi * t / tf)
                    ]
                if i == 1:
                    simulation.hamiltonian[i].energies = [
                        coefficients[1] * np.sin(np.pi * t / tf)
                    ]
                if i == 3:
                    simulation.hamiltonian[i].energies = [
                        coefficients[2] * (2 * t / tf - 1)
                    ]
        return True

    # Omega_g * Omega_r / delta
    res = simulation.performance_vs_time(
        2,
        schedule=lambda t, tf: experiment_rydberg_MIS_schedule(
            t, tf, coefficients=[Omega_g, Omega_r, Delta]),
        plot=True,
        verbose=False,
        method=['trotterize', 'odeint'],
        metric=['approximation_ratio', 'optimum_overlap'])

    return res
Example #8
0
def dephasing_performance():
    # adiabatic = SimulateAdiabatic(hamiltonian=[laser], noise = [dephasing, dissipation], noise_model='continuous',
    #                              graph=graph, IS_subspace=True, cost_hamiltonian=rydberg_hamiltonian_cost)
    # def schedule(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)
    # adiabatic.performance_vs_total_time(np.arange(5, 100, 5), schedule=schedule, verbose=True, plot=True, method='odeint')
    dephasing_rates = 10. ** (np.arange(-3, 0, .2))
    performance_3 = []
    performance_5 = []
    for j in [3, 5]:
        graph = line_graph(n=j)
        phi = .02
        laser = EffectiveOperatorHamiltonian(omega_g=np.cos(phi), omega_r=np.sin(phi), energies=(1,), graph=graph)
        dissipation = EffectiveOperatorDissipation(omega_g=np.cos(phi), omega_r=np.sin(phi), rates=(1,), graph=graph)
        dephasing = lindblad_operators.LindbladPauliOperator(pauli='Z', IS_subspace=True, graph=graph, rates=(.1,))
        rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=qubit)
        eq = LindbladMasterEquation(hamiltonians=[laser], jump_operators=[dissipation, dephasing])

        for i in range(len(dephasing_rates)):
            dissipation.rates = (1,)
            laser.energies = (1,)
            dephasing.rates = (dephasing_rates[i],)
            state = np.zeros(dissipation.nh_hamiltonian.shape)
            state[-1, -1] = 1
            state = State(state, is_ket=False, graph=graph, IS_subspace=True)
            ss = eq.steady_state(state)
            ss = ss[1][0]
            state = State(ss, is_ket=False, graph=graph, IS_subspace=True)
            print(rydberg_hamiltonian_cost.optimum_overlap(state))
            if j == 3:
                performance_3.append(rydberg_hamiltonian_cost.optimum_overlap(state))
            else:
                performance_5.append(rydberg_hamiltonian_cost.optimum_overlap(state))

    plt.scatter(dephasing_rates, performance_3, color='teal', label=r'$n=3$ line graph')
    plt.scatter(dephasing_rates, performance_5, color='purple', label=r'$n=5$ line graph')
    plt.ylabel(r'log(-log(optimum overlap))')
    plt.xlabel(r'$\log(\gamma\Omega^2/(\delta^2\Gamma_{\rm{dephasing}}))$')
    plt.legend()
    plt.show()
Example #9
0
def omega_vs_T(graph=None, mis=None, show_graph=False, n=3):
    schedule = lambda t, tf: [[t / tf, (tf - t) / tf, 1], [1]]
    if graph is None:
        graph, mis = line_graph(n=n)
    graph = Graph(graph)
    if show_graph:
        nx.draw(graph)
        plt.show()
    times = np.arange(20, 100, 10)
    omegas = np.arange(5, 8, .25)
    print(times, omegas)
    cost_function = []
    for i in range(len(times)):
        cost_function_detuning = []
        for j in range(len(omegas)):
            simulation = adiabatic_simulation(graph,
                                              noise_model='continuous',
                                              delta=omegas[j])
            results = master_equation.run_ode_solver(
                psi,
                0,
                times[i],
                num_from_time(times[i]),
                schedule=lambda t: schedule(t, times[i]))
            cost = rydberg_hamiltonian_cost.cost_function(results[-1],
                                                          is_ket=False) / mis
            print(times[i], omegas[j], cost)
            cost_function_detuning.append(cost)
        cost_function.append(cost_function_detuning)

    plt.imshow(cost_function,
               vmin=0,
               vmax=1,
               interpolation=None,
               extent=[0, max(omegas), max(times), 0],
               origin='upper')
    plt.xticks(np.linspace(0, max(omegas), 10))
    plt.yticks(np.linspace(0, max(times), 10))
    plt.colorbar()
    plt.xlabel(r'Rabi frequency $\Omega$')
    plt.ylabel(r'Annealing time $T$')
    plt.show()
Example #10
0
def run(n, t, gamma, omega):
    graph, mis = line_graph(n, return_mis=True)

    def rydberg_EIT_schedule(t, tf, coefficients=None):
        if coefficients is None:
            coefficients = [1, 1]
        for i in range(len(simulation_eit.hamiltonian)):
            if i == 0:
                # We don't want to update normal detunings
                simulation_eit.hamiltonian[i].energies = [t / tf * coefficients[0]]
            if i == 1:
                simulation_eit.hamiltonian[i].energies = [(tf - t) / tf * coefficients[1]]

        return True

    simulation_eit = eit_simulation(graph, noise_model='monte_carlo', gamma=gamma, delta=0)
    res = simulation_eit.performance_vs_total_time([t], schedule=lambda t, tf: rydberg_EIT_schedule(t, tf,
                                                                                              coefficients=[omega,
                                                                                                            omega]),
                                             plot=False, verbose=True, method='odeint', iterations=1)
    return res
Example #11
0
def time_performance():
    graph, mis = line_graph(3, return_mis=True)
    # graph, mis = degree_fails_graph(return_mis=True)
    graph = Graph(graph)
    ratios_d = [1]
    ratios_r = [1]
    for d in ratios_d:
        for r in ratios_r:
            print(d, r)

            def rydberg_EIT_schedule(t, tf, coefficients=None):
                if coefficients is None:
                    coefficients = [1, 1]
                for i in range(len(simulation_eit.hamiltonian)):
                    if i == 0:
                        # We don't want to update normal detunings
                        simulation_eit.hamiltonian[i].energies = [
                            t / tf * coefficients[0]
                        ]
                    if i == 1:
                        simulation_eit.hamiltonian[i].energies = [
                            (tf - t) / tf * coefficients[1]
                        ]

                return True

            simulation_eit = eit_simulation(graph,
                                            noise_model='continuous',
                                            gamma=1,
                                            delta=d,
                                            Omega_g=r,
                                            Omega_r=r)
            simulation_eit.performance_vs_total_time(
                [5, 10, 15, 20],
                metric='cost_function',
                schedule=lambda t, tf: rydberg_EIT_schedule(
                    t, tf, coefficients=[r, r]),
                plot=True,
                verbose=True,
                method='RK23')
Example #12
0
def time_evolve(product_state, disorder, T, method='ED'):
    L = len(disorder)

    graph = line_graph(L)
    heisenberg = ham.HamiltonianHeisenberg(graph,
                                           energies=(1 / 4, 1 / 4),
                                           subspace=0)

    index = np.argwhere(np.sum(heisenberg.states - product_state, axis=1) == 0)
    state = np.zeros((heisenberg.states.shape[0], 1))
    state[index] = 1

    if method == 'ED':
        disorder_hamiltonian_diag = np.sum(
            (1 / 2 - heisenberg.states) * disorder, axis=1)
        disorder_hamiltonian = np.diag(disorder_hamiltonian_diag)
        eigval, eigvec = np.linalg.eigh(disorder_hamiltonian +
                                        heisenberg.hamiltonian)
        return eigvec @ (np.multiply(
            np.e**(-1j * T * np.expand_dims(eigval, axis=-1)),
            (eigvec.conj().T @ state)))
    elif method == 'expm_multiply':
        disorder_hamiltonian = sparse.csc_matrix(
            (np.sum((1 / 2 - heisenberg.states) * disorder, axis=1),
             (np.arange(heisenberg.states.shape[0]),
              np.arange(heisenberg.states.shape[0]))),
            shape=(heisenberg.states.shape[0], heisenberg.states.shape[0]))
        return expm_multiply(
            -1j * T * (disorder_hamiltonian + heisenberg.hamiltonian), state)
    elif method == 'expm':
        disorder_hamiltonian = sparse.csc_matrix(
            (np.sum((1 / 2 - heisenberg.states) * disorder, axis=1),
             (np.arange(heisenberg.states.shape[0]),
              np.arange(heisenberg.states.shape[0]))),
            shape=(heisenberg.states.shape[0], heisenberg.states.shape[0]))
        return expm(-1j * T *
                    (disorder_hamiltonian + heisenberg.hamiltonian)) @ state
    else:
        raise NotImplementedError
Example #13
0
 def adiabatic_hamiltonian(t, tf):
     graph, mis = line_graph(n=n)
     ham = np.zeros((2**n, 2**n))
     coefficients = adiabatic_schedule(t, tf)
     rydberg_energy = 50
     rydberg_hamiltonian = hamiltonian.HamiltonianMIS(graph,
                                                      energy=rydberg_energy,
                                                      code=qubit)
     # TODO: generalize this!
     if n == 3:
         ham = ham + coefficients[1] * tools.tensor_product(
             [qubit.Z, np.identity(2),
              np.identity(2)])
         ham = ham + coefficients[1] * tools.tensor_product(
             [np.identity(2), qubit.Z,
              np.identity(2)])
         ham = ham + coefficients[1] * tools.tensor_product(
             [np.identity(2), np.identity(2), qubit.Z])
         ham = ham + coefficients[0] * tools.tensor_product(
             [qubit.X, np.identity(2),
              np.identity(2)])
         ham = ham + coefficients[0] * tools.tensor_product(
             [np.identity(2), qubit.X,
              np.identity(2)])
         ham = ham + coefficients[0] * tools.tensor_product(
             [np.identity(2), np.identity(2), qubit.X])
         ham = ham + np.diag(rydberg_hamiltonian.hamiltonian.T[0])
     elif n == 2:
         ham = ham + coefficients[1] * tools.tensor_product(
             [qubit.Z, np.identity(2)])
         ham = ham + coefficients[1] * tools.tensor_product(
             [np.identity(2), qubit.Z])
         ham = ham + coefficients[0] * tools.tensor_product(
             [qubit.X, np.identity(2)])
         ham = ham + coefficients[0] * tools.tensor_product(
             [np.identity(2), qubit.X])
         ham = ham + np.diag(rydberg_hamiltonian.hamiltonian.T[0])
     return np.linalg.eig(ham)
Example #14
0
def performance_vs_alpha():
    # alpha = gamma * omega^2/(delta^2 T)
    graph = line_graph(n=3)
    gammas = np.array([1, 5, 10])
    times = np.array([1, 5, 10])
    deltas = np.array([20, 30])
    omegas = np.array([1, 5, 10])
    for (g, d, o) in zip(gammas, deltas, omegas):
        # Find the performance vs alpha
        laser = EffectiveOperatorHamiltonian(graph=graph)
        dissipation = EffectiveOperatorDissipation(graph=graph)
        rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=qubit)
        adiabatic = SimulateAdiabatic(hamiltonian=[laser], noise = [dissipation], noise_model='continuous',
                                      graph=graph, IS_subspace=True, cost_hamiltonian=rydberg_hamiltonian_cost)
        def schedule(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)
        performance = adiabatic.performance_vs_total_time(times, schedule=schedule, verbose=True, method='odeint')[0]
        alphas = g * o**2/(d**2 * times)
        plt.scatter(alphas, performance)
    plt.show()
Example #15
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
Example #16
0
# coefficients=[Omega_g, Omega_r, Delta] [Omega, Delta]
# res, info = simulation.run(20, schedule=lambda t, tf: True, verbose=True, method='odeint', iter=10)
# print(res)
# res, info = simulation.performance_vs_time(100, schedule=lambda t, tf:
# experiment_rydberg_MIS_schedule(t, tf, coefficients=[Omega_g, Omega_r, Delta]), verbose=True, method='RK45', plot=True)
# experiment_rydberg_MIS_schedule(t, tf, coefficients=[1, 1, 1])
# simulation.noise_model = None
# simulation.performance_vs_time(10, schedule=lambda t, tf: experiment_rydberg_MIS_schedule(t, tf, coefficients=[15 * np.pi, 5.5 * np.pi, 2 * np.pi * 1.5]),
#                         plot=True, method='odeint', verbose=True)
# simulation.performance_vs_total_time(np.arange(5, 90, 5), schedule=lambda t, tf: simulation.rydberg_MIS_schedule(t, tf,
#                                                                                                           coefficients=[
#                                                                                                               Omega,
#                                                                                                               Delta]),
#                               plot=True, method='odeint', verbose=True)
graph = line_graph(2)
simulation_eit = eit_simulation(graph,
                                noise_model='continuous',
                                gamma=0,
                                delta=25,
                                Omega_g=5,
                                Omega_r=5)
"""

performance = simulation_eit.run(2000, schedule=lambda t, tf: rydberg_EIT_schedule(t, tf, coefficients=[1, 1]),
                                 verbose=True, method='odeint')
print(np.round(performance[0][-1], 2))

eigvals = simulation_eit.spectrum_vs_time(1, num=30, k=6, schedule=lambda t, tf: rydberg_EIT_schedule(t, tf, coefficients=[1, 1]), plot=True)
"""
Example #17
0
    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


#imperfect_blockade_performance()


graph = line_graph(n=3, return_mis=False)
phi = np.pi/2
laser = EffectiveOperatorHamiltonian(omega_g=np.cos(phi), omega_r=np.sin(phi), graph=graph)
eq = SchrodingerEquation(hamiltonians=[laser])

state = State(np.ones((5, 1), dtype=np.complex128)/np.sqrt(5))
print(np.round(eq.eig(k='all')[1], decimals=3))

def performance_vs_alpha():
    # alpha = gamma * omega^2/(delta^2 T)
    graph = line_graph(n=3)
    gammas = np.array([1, 5, 10])
    times = np.array([1, 5, 10])
    deltas = np.array([20, 30])
    omegas = np.array([1, 5, 10])
    for (g, d, o) in zip(gammas, deltas, omegas):
Example #18
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
Example #19
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()
Example #20
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
Example #21
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)
Example #22
0
    def test_hamiltonian_driver(self):
        N = 6

        hl_qubit = hamiltonian.HamiltonianDriver(
            graph=tools_test.sample_graph())

        psi0 = State(np.zeros((2**N, 1)))
        psi0[0, 0] = 1
        psi1 = State(tools.outer_product(psi0, psi0))

        # Evolve by e^{-i (\pi/2) \sum_i X_i}
        psi0 = hl_qubit.evolve(psi0, np.pi / 2)

        # Should get (-1j)^N |111111>
        self.assertTrue(np.vdot(psi0, psi0) == 1)
        self.assertTrue(psi0[-1, 0] == (-1j)**N)

        # Evolve by e^{-i (\pi/2) \sum_i X_i}
        psi1 = hl_qubit.evolve(psi1, np.pi / 2)

        # Should get (-1j)^N |111111>
        self.assertTrue(tools.is_valid_state(psi1))
        self.assertAlmostEqual(psi1[-1, -1], 1)

        psi0 = State(np.zeros((2**N, 1)))
        psi0[0, 0] = 1
        psi0 = hl_qubit.left_multiply(psi0)
        psi1 = np.zeros((2**N, 1), dtype=np.complex128)
        for i in range(N):
            psi1[2**i, 0] = 1
        self.assertTrue(np.allclose(psi0, psi1))
        psi2 = State(np.zeros((2**N, 1)))
        psi2[0, 0] = 1
        psi2 = hl_qubit.hamiltonian @ psi2
        self.assertTrue(np.allclose(psi0, psi2))

        N = 3
        hl = hamiltonian.HamiltonianDriver(transition=(0, 1), code=rydberg)
        psi0 = State(np.zeros((rydberg.d**N, 1)), code=rydberg)
        psi0[5, 0] = 1
        psi1 = State(tools.outer_product(psi0, psi0), code=rydberg)
        psi0 = hl.left_multiply(psi0)

        self.assertTrue(psi0[2, 0] == 1)
        self.assertTrue(psi0[14, 0] == 1)
        psi1 = hl.left_multiply(psi1)
        self.assertTrue(psi1[2, 5] == 1)
        self.assertTrue(psi1[14, 5] == 1)

        psi0 = State(np.zeros((rydberg.d**N, 1)), code=rydberg)
        psi0[5, 0] = 1
        psi0 = hl.evolve(psi0, np.pi / 2)
        self.assertTrue(np.isclose(psi0[11, 0], -1))

        # IS subspace
        hl = hamiltonian.HamiltonianDriver(transition=(0, 2),
                                           code=rydberg,
                                           IS_subspace=True,
                                           graph=line_graph(2))
        psi0 = State(np.zeros((8, 1)), code=rydberg)
        psi0[-1, 0] = 1
        psi0 = State(tools.outer_product(psi0, psi0), code=rydberg)
        self.assertTrue(tools.is_hermitian(hl.evolve(psi0, 1)))
Example #23
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
Example #24
0
rates = [
    0.010662442042852313, 0.016957472702683322, 0.02374938250983679,
    0.03498899357236483, 0.043702391822540175, 0.054663814324193705,
    0.06593339301684226
]
diss = [
    0.2927448927120103, 0.40019282741113876, 0.5126483512648607,
    0.6198496428799345, 0.7245172743824079, 0.8360234218829589,
    0.9456842157184615
]
print(np.diff(rates))
plt.plot(np.arange(4, 2 * len(diss) + 4, 2), diss)
plt.scatter(np.arange(4, 2 * len(diss) + 4, 2), diss)

plt.plot(np.arange(4, 2 * len(rates) + 4, 2), rates)
plt.scatter(np.arange(4, 2 * len(rates) + 4, 2), rates, c='black')
plt.show()

if __name__ == "__main__":
    n = int(sys.argv[1])
    res, error = alpha_correction_ar(graph=line_graph(n),
                                     mode='reit',
                                     which='S')
    print(res, error, flush=True)
"""
Compute <E>:
- function which at a given time, computes all the "bad" rates and dots them with the difference between the final 
eigenvalues and the final ground state energy.
"""
Example #25
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
Example #26
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))
Example #27
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)
Example #28
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()
Example #29
0
                    states[i].conj() @ qubit.left_multiply(
                        State(states[index].T), [j], qubit.Z))**2)[0, 0]
        # Select the relevant rates from 'good' to 'bad'
        print(rates)
        return rates

    for i in range(len(times)):
        print(times[i])
        schedule(times[i], 1)
        full_rates = full_rates + compute_rate()
        eigval, eigvec = eq.eig(k='all')
    return full_rates, eigval


n = 9
graph = line_graph(n)
rates, eigvals = rate_vs_eigenenergy([.5], graph=graph, which='S')
print(rates)
eigvals = np.abs(eigvals - eigvals[0])
eigvals = np.delete(eigvals, 0)
#plt.hist(eigvals, bins=30, weights=rates)
#res = np.polyfit(eigvals, np.log(rates), 1)
#print(res)
# What is the energy spacing
plt.scatter(eigvals, rates)
#print(res[0]*np.mean(np.diff(eigvals)[0:6]))
#plt.plot(eigvals, np.e**(res[0]*eigvals + res[1]))
plt.semilogy()
#plt.ylabel(r'$\sum_i \int_0^1 ds |\langle j |c_i| 0 \rangle|^2$')
#plt.xlabel('final independendent set size')
plt.ylabel(r'$\sum_i|\langle j |c_i| k \rangle|^2$')