Esempio n. 1
0
def Q(eq: SchrodingerEquation, dissipation):
    # Diagonalize Hamiltonian
    # Compute Q matrix elements
    eigval, eigvec = eq.eig()
    q = np.zeros((len(eigval), len(eigval)))
    jump_operators = np.array(dissipation.jump_operators)
    # For each pair of eigenvectors
    for pair in itertools.product(range(eigvec.shape[0]), repeat=2):
        # Compute the rate
        if pair[0] != pair[1]:
            eigvec1 = State(tools.outer_product(eigvec[pair[0]].T,
                                                eigvec[pair[0]].T),
                            is_ket=False,
                            IS_subspace=True,
                            graph=graph)
            eigvec2 = State(tools.outer_product(eigvec[pair[1]].T,
                                                eigvec[pair[1]].T),
                            is_ket=False,
                            IS_subspace=True,
                            graph=graph)

            rates = np.sum([
                np.trace(eigvec2 @ jump_operators[i] @ eigvec1
                         @ jump_operators[i].conj().T)
                for i in range(len(jump_operators))
            ])
            q[pair[1], pair[0]] = rates.real**2
            q[pair[0], pair[0]] = q[pair[0], pair[0]] - rates.real**2
    return q
Esempio n. 2
0
    def spectrum_vs_time(self, time, schedule, k=2, num=None, plot=False, which='S', hamiltonian=True):
        """Solves for the small (S) or large (L) energy sector."""
        if num is None:
            num = self._num_from_time(time)
        times = np.linspace(0, time, num=num)
        if not hamiltonian and (self.noise_model is None or self.noise_model is 'monte_carlo'):
            print('No noise models found. Finding Hamiltonian spectrum')
            hamiltonian = True
        if self.noise_model is None or self.noise_model is 'monte_carlo' or hamiltonian:
            # Initialize Schrodinger equation
            schrodinger_equation = SchrodingerEquation(hamiltonians=self.hamiltonian)
            eigvals = np.zeros((len(times), k), dtype=np.float64)
            for i in range(len(times)):
                schedule(times[i], time)
                eigval, eigvec = schrodinger_equation.eig(which=which, k=k)
                if which == 'S':
                    eigvals[i] = eigval[0:k]
                elif which == 'L':
                    eigvals[i] = eigval[len(eigval)-k-1:-1]
            if plot:
                plotted_eigvals = np.swapaxes(eigvals, 0, 1)
                for i in range(k):
                    plt.scatter(times, plotted_eigvals[i], color='teal')
                plt.ylabel('Energy')
                plt.xlabel('Time')
                plt.show()
        else:
            eigvals = np.zeros((len(times), self.cost_hamiltonian.shape[0], self.cost_hamiltonian.shape[0]),
                               dtype=np.complex128)
            raise NotImplementedError

        return eigvals
Esempio n. 3
0
def jump_rate_scaling():
    graph = Graph(nx.star_graph(n=4))  # line_graph(n=3)
    energy = 1
    phis = np.arange(.001, .01, .001)
    rates = np.zeros(len(phis))
    rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph,
                                                          IS_subspace=True,
                                                          code=qubit)
    print(rydberg_hamiltonian_cost.hamiltonian)
    for d in range(len(phis)):
        print(d)
        laser = EffectiveOperatorHamiltonian(omega_g=np.cos(phis[d]),
                                             omega_r=np.sin(phis[d]),
                                             energies=(energy, ),
                                             graph=graph)
        dissipation = EffectiveOperatorDissipation(omega_g=np.cos(phis[d]),
                                                   omega_r=np.sin(phis[d]),
                                                   rates=(energy, ),
                                                   graph=graph)
        # Find the dressed states
        simulation = SchrodingerEquation(hamiltonians=[laser])
        eigval, eigvec = simulation.eig()
        eigval = [
            rydberg_hamiltonian_cost.approximation_ratio(
                State(eigvec[i].T, is_ket=True, graph=graph, IS_subspace=True))
            for i in range(eigval.shape[0])
        ]
        print(eigval)
        optimal_eigval_index = np.argmax(eigval)
        optimal_eigval = eigvec[optimal_eigval_index]
        rate = 0
        for i in range(graph.n):
            # Compute the decay rate of the MIS into other states
            for j in range(eigvec.shape[0]):
                if j != optimal_eigval_index:
                    rate += np.abs(eigvec[j] @ dissipation.jump_operators[i]
                                   @ optimal_eigval.T)**2
        rates[d] = rate
    fit = np.polyfit(np.log(phis), np.log(rates), deg=1)

    plt.scatter(np.log(phis), np.log(rates), color='teal')
    plt.plot(np.log(phis),
             fit[0] * np.log(phis) + fit[1],
             color='k',
             label=r'$y=$' + str(np.round(fit[0], decimals=2)) + r'$x+$' +
             str(np.round(fit[1], decimals=2)))
    plt.legend()
    plt.xlabel(r'$\log(\phi)$')
    plt.ylabel(r'$\log(\rm{rate})$')
    plt.show()
Esempio n. 4
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
Esempio n. 5
0
        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):
        # 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)
Esempio n. 6
0
def rate_vs_eigenenergy(times,
                        graph=line_graph(n=2),
                        mode='hybrid',
                        which='S'):
    """For REIT, compute the total leakage from the ground state to a given state. Plot the total leakage versus
    the final eigenenergy"""
    if which == 'S':
        index = 0
    elif which == 'L':
        index = -1
    else:
        index = which

    # Good is a list of good eigenvalues
    # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good'
    def schedule_hybrid(t, tf):
        phi = (tf - t) / tf * np.pi / 2
        energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), )
        laser.omega_g = np.cos(phi)
        laser.omega_r = np.sin(phi)
        dissipation.omega_g = np.cos(phi)
        dissipation.omega_r = np.sin(phi)

    def schedule_reit(t, tf):
        phi = (tf - t) / tf * np.pi / 2
        laser.omega_g = np.cos(phi)
        laser.omega_r = np.sin(phi)
        dissipation.omega_g = np.cos(phi)
        dissipation.omega_r = np.sin(phi)

    def schedule_adiabatic(t, tf):
        phi = (tf - t) / tf * np.pi / 2
        energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), )
        laser.omega_g = np.sqrt(np.abs(np.sin(phi) * np.cos(phi)))
        laser.omega_r = np.sqrt(np.abs(np.sin(phi) * np.cos(phi)))
        dissipation.omega_g = np.sqrt(np.abs(np.sin(phi) * np.cos(phi)))
        dissipation.omega_r = np.sqrt(np.abs(np.sin(phi) * np.cos(phi)))

    laser = EffectiveOperatorHamiltonian(graph=graph,
                                         IS_subspace=True,
                                         energies=(1, ),
                                         omega_g=np.cos(np.pi / 4),
                                         omega_r=np.sin(np.pi / 4))
    energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True,
                                                      graph=graph,
                                                      energies=(2.5, ),
                                                      index=0)
    dissipation = EffectiveOperatorDissipation(graph=graph,
                                               omega_r=1,
                                               omega_g=1,
                                               rates=(1, ))
    if mode == 'hybrid':
        schedule = schedule_hybrid
    elif mode == 'adiabatic':
        schedule = schedule_adiabatic
    elif mode == 'reit':
        schedule = schedule_reit
    if mode != 'reit':
        eq = SchrodingerEquation(hamiltonians=[laser, energy_shift])
    else:
        eq = SchrodingerEquation(hamiltonians=[laser])

    def compute_rate():
        # Construct the first order transition matrix
        global full_rates
        energies, states = eq.eig(k='all')
        states = states.T
        rates = np.zeros(energies.shape[0]**2)
        for op in dissipation.jump_operators:
            rates = rates + (np.abs(states.conj().T @ op @ states)**
                             2).flatten()
        # Select the relevant rates from 'good' to 'bad'

        rates = np.reshape(
            rates.real,
            (graph.num_independent_sets, graph.num_independent_sets))
        return rates[:, index].flatten()

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