Esempio n. 1
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()
Esempio n. 2
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()
Esempio n. 3
0
def eit_steady_state(graph, show_graph=False, gamma=1):
    if show_graph:
        nx.draw(graph)
        plt.show()
    # Generate the driving and Rydberg Hamiltonians
    laser1 = hamiltonian.HamiltonianDriver(transition=(1, 2),
                                           IS_subspace=True,
                                           graph=graph,
                                           code=rydberg)
    laser2 = hamiltonian.HamiltonianDriver(transition=(0, 1),
                                           IS_subspace=True,
                                           graph=graph,
                                           code=rydberg)
    rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph,
                                                          IS_subspace=True,
                                                          code=rydberg)
    spontaneous_emission = lindblad_operators.SpontaneousEmission(
        graph=graph,
        transition=(1, 2),
        rates=[gamma],
        IS_subspace=True,
        code=rydberg)

    # Initialize adiabatic algorithm
    simulation = SimulateAdiabatic(graph,
                                   hamiltonian=[laser1, laser2],
                                   cost_hamiltonian=rydberg_hamiltonian_cost,
                                   IS_subspace=True,
                                   noise_model='continuous',
                                   code=rydberg,
                                   noise=[spontaneous_emission])

    master_equation = LindbladMasterEquation(
        hamiltonians=[laser1, laser2], jump_operators=[spontaneous_emission])
    initial_state = State(tools.outer_product(
        np.array([[0, 0, 0, 0, 0, 0, 0, 1]]).T,
        np.array([[0, 0, 0, 0, 0, 0, 0, 1]]).T),
                          code=rydberg,
                          IS_subspace=True,
                          is_ket=False)

    print(master_equation.steady_state(initial_state))

    return simulation
Esempio n. 4
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
Esempio n. 5
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()

graph, mis = two_triangle()
"""nx.draw(graph)
plt.show()"""
# Generate the driving and Rydberg Hamiltonians

# Initialize spontaneous emission
IS_penalty = 20
mis_dissipation = lindblad_operators.MISDissipation(graph,
                                                    IS_penalty=IS_penalty,
                                                    code=qubit)
hadamard_dissipation = Hadamard_Dissipation(code=qubit)
rydberg = hamiltonian.HamiltonianMIS(graph, energies=[IS_penalty], code=qubit)
# Initialize master equation
master_equation = LindbladMasterEquation(jump_operators=[mis_dissipation])

# Begin with all qubits in the ground codes
psi = tools.equal_superposition(graph.number_of_nodes())
psi = State(tools.outer_product(psi, psi))

dt = 0.1


def ARvstime(tf=10, schedule=lambda t, tf: [[], [t / tf, (tf - t) / tf]]):
    def ground_overlap(state):
        g = np.array([[0, 0], [0, 1]])
        op = tools.tensor_product([g] * graph.number_of_nodes())
        return np.real(np.trace(op @ state))

    t_cutoff = 5
Esempio n. 7
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()
Esempio n. 8
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))
Esempio n. 9
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)
Esempio n. 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)
Esempio n. 11
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
Esempio n. 12
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
Esempio n. 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
Esempio n. 14
0
    def run(self, time, schedule, num=None, initial_state=None, full_output=True, method='RK45', verbose=False,
            iterations=None):
        if method == 'odeint' or method == 'trotterize' and num is None:
            num = self._num_from_time(time, method=method)

        if initial_state is None:
            # Begin with all qudits in the ground s
            initial_state = State(np.zeros((self.cost_hamiltonian.hamiltonian.shape[0], 1)), code=self.code,
                                  IS_subspace=self.IS_subspace, graph=self.graph)
            initial_state[-1, -1] = 1

        if self.noise_model is not None and self.noise_model != 'monte_carlo':
            initial_state = State(outer_product(initial_state, initial_state), IS_subspace=self.IS_subspace,
                                  code=self.code, graph=self.graph)

        if self.noise_model == 'continuous':
            # Initialize master equation
            if method == 'trotterize':
                master_equation = LindbladMasterEquation(hamiltonians=self.hamiltonian, jump_operators=self.noise)
                results, info = master_equation.run_trotterized_solver(initial_state, 0, time, num=num,
                                                                       schedule=lambda t: schedule(t, time),
                                                                       full_output=full_output, verbose=verbose)
            else:
                master_equation = LindbladMasterEquation(hamiltonians=self.hamiltonian, jump_operators=self.noise)
                results, info = master_equation.run_ode_solver(initial_state, 0, time, num=num,
                                                               schedule=lambda t: schedule(t, time), method=method,
                                                               full_output=full_output, verbose=verbose)
        elif self.noise_model is None:
            # Noise model is None
            # Initialize Schrodinger equation
            schrodinger_equation = SchrodingerEquation(hamiltonians=self.hamiltonian)
            if method == 'trotterize':
                results, info = schrodinger_equation.run_trotterized_solver(initial_state, 0, time, num=num,
                                                                            verbose=verbose, full_output=full_output,
                                                                            schedule=lambda t: schedule(t, time))
            else:
                results, info = schrodinger_equation.run_ode_solver(initial_state, 0, time, num=num, verbose=verbose,
                                                                    schedule=lambda t: schedule(t, time), method=method,
                                                                    full_output=full_output)

        else:
            assert self.noise_model == 'monte_carlo'
            # Initialize master equation
            master_equation = LindbladMasterEquation(hamiltonians=self.hamiltonian, jump_operators=self.noise)
            results, info = master_equation.run_stochastic_wavefunction_solver(initial_state, 0, time, num=num,
                                                                               full_output=full_output,
                                                                               schedule=lambda t: schedule(t, time),
                                                                               method=method, verbose=verbose,
                                                                               iterations=iterations)

        if len(results.shape) == 2:
            # The algorithm has output a single state
            out = [State(results, IS_subspace=self.IS_subspace, code=self.code, graph=self.graph)]
        elif len(results.shape) == 3:
            # The algorithm has output an array of states
            out = [State(res, IS_subspace=self.IS_subspace, code=self.code, graph=self.graph) for res in results]
        else:
            assert len(results.shape) == 4
            if self.noise_model != 'monte_carlo':
                raise Exception('Run output has more dimensions than expected')
            out = []
            for i in range(results.shape[0]):
                # For all iterations
                res = []
                for j in range(results.shape[1]):
                    # For all times
                    res.append(
                        State(results[i, j, ...], IS_subspace=self.IS_subspace, code=self.code, graph=self.graph))
                out.append(res)
        return out, info