Exemple #1
0
def test_lapack():
    import scipy.linalg.lapack as lapak
    import numpy as np
    A = np.zeros((2, 2), dtype=complex)
    A[0][0] = 0.0
    A[0][1] = 0.0 - 1j
    A[1][0] = 0.0 + 1j
    A[1][1] = 0.0
    eig = lapak.zheevd(A)
    # in the first array are the eigenvalues
    print(eig[0][0], eig[0][1])
    # and in the 2nd array are the eigenvector, as the columns
    for j in range(0, 2):
        print(eig[1][j][0])
    print(eig[1][0][0], eig[1][1][0])
Exemple #2
0
def simulate_SPB(
    R_t=None,  #Position of molecule as function of time in XYZ coordinate system
    T=None,  #Total time for which molecule is simulated
    E_R=None,
    B_R=None,  #Spatial profiles of the static electric and magnetic fields
    microwave_fields=None,  #List of microwave fields for the simulation
    initial_states=None,  #Initial states for the system (can simulate multiple initial states with little additional cost)
    final_state=None,  #Desired final state after the state preparation
    N_steps=int(1e4),  #Number of timesteps for time-evolution
    H_path=None,  #Path to Hamiltonian if not the default
    verbose=False,  #Whether or not need to print a bunch of output
    plots=False  #Whether or not to save plots
):
    """
    Function that simulates state preparation B in CeNTREX.

    The structure of the cod is as follows:
    0. Define the position of the molecule as a function of time. Position is defined in
       the capitalized coordinate system(XYZ where Z is along the beamline). Helps with
       defining time-dependence of e.g. microwave intensities and electric and magnetic fields.
    
    1. Define electric and magnetic fields as a function of time. This is done based on 
       spatial profiles of the EM-fields. The coordinate system for the direction of the
       the fields is different from the coordinate system used for defining the spatial
       profile:
        - For defining spatial profile use XYZ (Z is along beamline)
        - For defining direction of fields use xyz where z is along the electric field
          in the Main Interaction region
       For electric fields should use V/cm and for B-fields G.

    2. Define slowly time-varying Hamiltonian. This is the Hamiltonian due to the internal
       dynamics of the molecule and the external DC electric and magnetic fields
       (maybe split into internal Hamiltonian and EM-field Hamiltonian?)

    3. Define the microwave Hamiltonian. Simply the couplings due to the microwaves.
       Rotating wave approximation is applied and the rotating frame is used.

    4. Time-evolve the system by using matrix exponentiation for solving Schroedinger eqn.

    5. Make plots etc. if needed
    """
    ### 0. Position as function of time
    #Check if position as function of time was provided, otherwise use a default trajectory
    if R_t is None:

        def molecule_position(t, r0, v):
            """
            Functions that returns position of molecule at a given time for given initial position and velocity.
            inputs:
            t = time in seconds
            r0 = position of molecule at t = 0 in meters
            v = velocity of molecule in meters per second
            
            returns:
            r = position of molecule in metres
            """
            r = r0 + v * t

            return r

        #Define the position of the molecule as a function of time
        r0 = np.array((0, 0, -100e-3))
        v = np.array((0, 0, 200))
        R_t = lambda t: molecule_position(t, r0, v)

        #Define the total time for which the molecule is simulated
        z0 = r0[2]
        vz = v[2]
        T = np.abs(2 * z0 / vz)

    ### 1. Electric and magnetic fields as function of time
    #Here we determine the E- and B-fields as function of time based on provided spatial
    #profiles of the fields

    #Electric field:
    if E_R is not None:
        E_t = lambda t: E_R(R_t(t))

    #If spatial profile is not provided, assume a uniform 50 V/cm along z
    else:
        E_t = lambda t: np.array((0, 0, 50.))

    #Magnetic field:
    if B_R is not None:
        B_t = lambda t: B_R(R_t(t))

    #If spatial profile is not provided assume uniform 0.001 G along z
    else:
        B_t = lambda t: np.array((0, 0, 0.001))

    ### 2. Slowly time-varying Hamiltonian
    #Make list of quantum numbers that defines the basis for the matrices
    QN = make_QN(0, 3, 1 / 2, 1 / 2)
    dim = len(QN)

    #Get H_0 from file (H_0 should be in rad/s)
    if H_path is None:
        H_0_EB = make_hamiltonian(
            "./hamiltonians/TlF_X_state_hamiltonian0to3_2020_03_03.py")
    else:
        H_0_EB = make_hamiltonian(H_path)

    #Calculate the field free Hamiltonian
    H_0 = H_0_EB(np.array((0, 0, 0)), np.array((0, 0, 0)))

    #Calculate part of the Hamiltonian that is due to electromagnetic fields
    H_EB_t = lambda t: H_0_EB(E_t(t), B_t(t)) - H_0

    #Check that H_0 is hermitian
    H_test = H_0 + H_EB_t(T / 2)
    is_herm = np.allclose(H_test, np.conj(H_test.T))
    if not is_herm:
        print("H_0 is non-hermitian!")

    ### 3. Microwave Hamiltonians
    #Generate the part of the Hamiltonian that describes the effect of the microwave
    #field(s)
    if microwave_fields is not None:
        counter = 0
        #Containers for microwave coupling Hamiltonians and the microwave frequencies
        microwave_couplings = []
        omegas = []
        D_mu = np.zeros(H_0.shape)
        for microwave_field in microwave_fields:
            if verbose:
                counter += 1
                print("\nMicrowave {:}:".format(counter))
            #Find out where the peak intensity of the field is located
            Z_peak = microwave_field.z0
            R_peak = np.array((0, 0, Z_peak))

            #Determine the Hamiltonian at z0
            H_peak = H_0_EB(E_R(R_peak), B_R(R_peak))

            #Find the exact ground and excited states for the field at z_peak
            microwave_field.find_closest_eigenstates(H_peak, QN)

            #Calculate angular part of matrix element for main transition
            ME_main = microwave_field.calculate_ME_main(
                pol_vec=microwave_field.p_t(
                    0))  #Angular part of ME for main transition

            #Find the coupling matrices due to the microwave
            H_list = microwave_field.generate_couplings(QN)
            H_list = [H / ME_main for H in H_list]
            Hu_list = [np.triu(H) for H in H_list]
            Hl_list = [np.tril(H) for H in H_list]

            #Find some necessary parameters and then define the coupling matrix as a function of time
            Omega_t = microwave_field.find_Omega_t(
                R_t)  #Time dependence of Rabi rate
            p_t = microwave_field.p_t  #Time dependence of polarization of field
            omega = np.abs(microwave_field.calculate_frequency(
                H_peak, QN))  #Calculate frequency of transition
            omegas.append(omega)
            D_mu += microwave_field.generate_D(
                np.sum(omegas), H_peak,
                QN)  #Matrix that shifts energies for rotating frame

            #Define the coupling matrix as function of time
            def H_mu_t_func(Hu_list, Hl_list, p_t, Omega_t, t):
                return (
                    1 / 2 * Omega_t(t) *
                    (Hu_list[0] * p_t(t)[0] + Hu_list[1] * p_t(t)[1] +
                     Hu_list[2] * p_t(t)[2] + Hl_list[0] * p_t(t)[0].conj() +
                     Hl_list[1] * p_t(t)[1].conj() +
                     Hl_list[2] * p_t(t)[2].conj()))

            H_mu_t = partial(H_mu_t_func, Hu_list, Hl_list, p_t, Omega_t)
            microwave_couplings.append(H_mu_t)

            #Print output for checks
            if verbose:
                print("ME_main = {:.3E}".format(ME_main))
                print("muW frequency: {:.9E} GHz".format(omega /
                                                         (2 * np.pi * 1e9)))
                print("ground_main:")
                ground_main = microwave_field.ground_main
                ground_main.print_state()
                print("excited_main:")
                excited_main = microwave_field.excited_main
                excited_main.print_state()
                ME = excited_main.state_vector(QN).conj().T @ H_mu_t(
                    T / 2) @ ground_main.state_vector(QN)
                print("Omega_T/2 = {:.3E}".format(ME / (2 * np.pi)))

        #Generate function that gives couplings due to all microwaves
        def H_mu_tot_t(t):
            H_mu_tot = microwave_couplings[0](t)
            if len(microwave_couplings) > 1:
                for H_mu_t in microwave_couplings[1:]:
                    H_mu_tot = H_mu_tot + H_mu_t(t)
            return H_mu_tot

    else:
        H_mu_tot_t = lambda t: np.zeros(H_0.shape)

    if verbose:
        time = timeit.timeit("H_mu_tot_t(T/2)", number=10,
                             globals=locals()) / 10
        print("Time to generate H_mu_tot_t: {:.3e} s".format(time))
        H_test = H_mu_tot_t(T / 2)
        non_zero = H_test[np.abs(H_test) > 0].shape[0]
        print("Non-zero elements at T/2: {}".format(non_zero))
        print("Rotating frame energy shifts:")
        print(np.diag(D_mu) / (2 * np.pi * 1e9))
        print(np.max(np.abs(H_mu_tot_t(T / 2))) / (2 * np.pi))

    ### 4. Time-evolution
    #Now time-evolve the system by repeatedly applying the time-evolution operator with small
    # timestep

    #Make array of times at which time-evolution is performed
    t_array = np.linspace(0, T, N_steps)

    #Calculate timestep
    dt = T / N_steps

    #Set the state vector to the initial state
    H_t0 = H_0 + H_EB_t(0)
    psis = np.zeros((len(initial_states), H_t0.shape[0]), dtype=complex)
    ini_index = np.zeros(len(initial_states))
    for i, initial_state in enumerate(initial_states):
        initial_state = find_closest_state(H_t0, initial_state, QN)
        psis[i, :] = initial_state.state_vector(QN)
        #Also figure out the state indices that correspond to the initial states
        ini_index[i] = find_state_idx_from_state(H_t0, initial_state, QN)

    #Set up containers to store results
    state_probabilities = np.zeros(
        (len(initial_states), len(t_array), H_t0.shape[0]))
    state_energies = np.zeros((len(t_array), H_t0.shape[0]))
    psi_t = np.zeros((len(initial_states), len(t_array), H_t0.shape[0]),
                     dtype=complex)

    #Initialize the reference matrix of eigenvectors
    E_ref, V_ref = np.linalg.eigh(H_t0)
    E_ref_0 = E_ref
    V_ref_0 = V_ref

    #Loop over timesteps to evolve system in time
    for i, t in enumerate(tqdm(t_array)):
        #Calculate the necessary Hamiltonians at this time
        H_t = H_0 + H_EB_t(t)
        H_mu = H_mu_tot_t(t)

        #Diagonalize H_t and transform to that basis
        D_t, V_t, info_t = zheevd(H_t)
        if info_t != 0:
            print("zheevd didn't work for H_0")
            D_t, V_t = np.linalg.eigh(H_t)

        #Make intermediate hamiltonian by transforming H to the basis where H_0 is diagonal
        H_I = V_t.conj().T @ H_t @ V_t

        #Sort the eigenvalues so they are in ascending order
        index = np.argsort(D_t)
        D_t = D_t[index]
        V_t = V_t[:, index]

        #Find the microwave coupling matrix in the new basis:
        H_mu = V_t.conj().T @ H_mu @ V_t

        #Make total intermediate hamiltonian
        H_I = H_I + H_mu

        #Transform H_I to the rotating basis
        H_R = H_I + D_mu

        #Diagonalize H_R
        D_R, V_R, info_R = zheevd(H_R)
        if info_R != 0:
            print("zheevd didn't work for H_R")
            D_R, V_R = np.linalg.eigh(H_R)

        #Reorder the eigenstates so that a given index corresponds to the same "adiabatic" state
        energies, evecs = D_t, V_t
        energies, evecs = reorder_evecs(evecs, energies, V_ref)

        #Propagate state vector in time
        propagator = V_t @ V_R @ np.diag(np.exp(
            -1j * D_R * dt)) @ V_R.conj().T @ V_t.conj().T
        for j in range(0, len(initial_states)):
            psis[j, :] = propagator @ psis[j, :]

            #Calculate the overlap of the state vector with all of the eigenvectors of the Hamiltonian
            overlaps = np.dot(np.conj(psis[j, :]).T, evecs)
            probabilities = overlaps * np.conj(overlaps)

            #Store the probabilities, energies and the state vector
            state_probabilities[j, i, :] = np.real(probabilities)
            psi_t[j, i, :] = psis[j, :].T

        state_energies[i, :] = energies
        V_ref = evecs

    #Find the exact form of the desired final state and calculate overlap with state vector
    final_state = find_closest_state(H_0 + H_EB_t(T), final_state, QN)
    final_state_vec = final_state.state_vector(QN)

    if len(initial_states) == 1:
        overlap = final_state_vec.conj().T @ psis[0, :]
        probability = np.abs(overlap)**2

        if verbose:
            print(
                "Probability to end up in desired final state: {:.3f}".format(
                    probability))
            print("desired final state|fin> = ")
            final_state.print_state()

    return t_array, state_probabilities, V_ref, QN
    #Set system to its initial state
    psi = initial_state_vec

    #Loop over timesteps to evolve system in time
    for i in tqdm(range(0, N_steps)):
        #Calculate the time
        t = (i + 1) * dt

        #Calculate the necessary Hamiltonians at this time
        H_0 = H_0_t(t)
        H_mu1_i = H_mu1(t)
        H_mu2_i = H_mu2(t)

        #Diagonalize H_0 and transform to that basis
        D_0, V_0, info_0 = zheevd(H_0)
        if info_0 != 0:
            print("zheevd didn't work for H_0")
            D_0, V_0 = np.linalg.eigh(H_0)
        #Make intermediate hamiltonian by transforming H to the basis where H_0 is diagonal
        H_I = V_0.conj().T @ H_0 @ V_0

        #Sort the eigenvalues so they are in ascending order
        index = np.argsort(D_0)
        D_0 = D_0[index]
        V_0 = V_0[:, index]

        #Find the microwave coupling matrix:
        H_mu1_i = V_0.conj().T @ H_mu1_i @ V_0 * np.exp(1j * omega_mu1 * t)
        H_mu1_i = block_diag(H_mu1_i[0:16, 0:16], np.zeros(
            (dim - 16, dim - 16)))
Exemple #4
0
def propagate_state(lens_state_vec,
                    H,
                    QN,
                    B,
                    E,
                    T,
                    N_steps,
                    save_fields=False):
    """
    Function that propagates the state of a quantum system defined by 
    Hamiltonian H from t = 0 to t=T. The initial state of the system is the 
    eigenstate of the Hamiltonian H that has the highest overlap with 
    initial_state_vec. The Hamiltonian may include time-dependent EM fields
    defined by E and B.
    
    Note: the function assumes that the E- and B-fields at times t = 0 and 
    t = T are the same. This is done in order to be able to compare the initial
    and final state vectors.
    
    inputs:
    initial_state_vec = defines initial state of system
    H = Hamiltonian of system as function of B and E
    QN = list that defines the basis of the Hamiltonian and state vectors
    B = magnetic field as function of time
    E = electric field as function of time
    T = total time for which to propagate the state
    save_fields = Boolean that determines if EM fields as function of time should be saved
    
    outputs:
    probability = overlap**2 of the initial and final state vectors
    """

    #Find the initial state by diagonalizing the Hamiltonian at t=0 and finding
    #which of the eigenstates is closest to initial_state_vec

    #Diagonalize H
    energies0, evecs0 = np.linalg.eigh(H(E(0), B(0)))

    #Find the index of the state corresponding to the lens state
    index_ini = find_state_idx(lens_state_vec, evecs0, n=1)

    #Find the exact state vector of the initial state
    initial_state_vec = evecs0[:, index_ini:index_ini + 1]

    #Define initial state
    psi = initial_state_vec

    #If fields are to be saved, initialize containers
    if save_fields:
        E_field = np.zeros((3, N_steps))
        B_field = np.zeros((3, N_steps))
        t_array = np.zeros((N_steps))

        E_field[:, 0] = E(0)
        B_field[:, 0] = B(0)

    #Calculate timestep
    dt = T / N_steps

    #Loop over timesteps to evolve system in time:
    t = 0
    for n in range(0, N_steps):
        #Calculate time for this step
        t += dt

        #Calculate fields
        E_t = E(t)
        B_t = B(t)

        #Evaluate hamiltonian at this time
        H_i = H(E_t, B_t)

        #Diagonalize the hamiltonian
        D, V, info = zheevd(H_i)

        #If zheevd doesn't converge, use numpy instead
        if info != 0:
            D, V = np.linalg.eigh(H_i)

        #Propagate the state vector
        psi = V @ np.diag(np.exp(-1j * D * dt)) @ np.conj(V.T) @ psi

        #If fields are saved, add to array
        if save_fields:
            E_field[:, n] = E_t
            B_field[:, n] = B_t
            t_array[n] = t

    #Determine which eigenstate of the Hamiltonian corresponds to the lens state
    #in the final values of the E- and B-fields
    #Diagonalize H
    energiesT, evecsT = np.linalg.eigh(H(E(t), B(t)))

    #Find the index of the state corresponding to the lens state
    index_fin = find_state_idx(lens_state_vec, evecsT, n=1)

    #Find the exact state vector that corresponds to the lens state in the given
    #E and B field
    final_state_vec = evecsT[:, index_fin:index_fin + 1]

    #Calculate overlap between the initial and final state vector
    overlap = np.dot(np.conj(psi).T, final_state_vec)
    probability = np.abs(overlap)**2

    #Initialize dictionary to store results
    results_dict = {"probability": probability}

    if save_fields:
        results_dict["E_field"] = E_field
        results_dict["B_field"] = B_field
        results_dict["t_array"] = t_array

    #Return probability of staying in original state
    return results_dict
Exemple #5
0
def von_neumann(rho):
    d = rho.shape[0]
    b = lapak.zheevd(rho)
    VnE = shannon(b[0])
    return VnE
Exemple #6
0
def simulate_RAP(r0=np.array((0, 0, -100e-3)),
                 v=np.array((0, 0, 200)),
                 ring_z1=-71.4375e-3,
                 ring_z2=85.725e-3,
                 ring_V1=4e3,
                 ring_V2=3.6e2,
                 B_earth=np.array((0, 0, 0)),
                 Omega1=2 * np.pi * 200e3,
                 Omega2=2 * np.pi * 200e3,
                 Delta=0,
                 delta=0,
                 z0_mu1=0.0,
                 z0_mu2=0.03,
                 N_steps=1e5):
    """
    Function that runs the rapid adiabatic passage simulation for the given 
    parameters
    
    inputs:
    r0 = initial position of molecule [m]
    v = velocity of molecule (assumed to be constant) [m/s]
    ring_z1 = position of first ring electrode [m]
    ring_z2 = position of second ring electrode [m]
    ring_V1 = voltage on ring 1 [V]
    ring_V2 = voltage on ring 2 [V]
    B_earth = magnetic field of earth [G]
    Omega1 = Rabi rate for microwave 1 [rad/s]
    Omega2 = Rabi rate for microwave 2 [rad/s]
    Delta = 1-photon detuning [rad/s]
    delta = 2-photon detuning [rad/s]
    z0_mu1 = z-position of microwave 1 [m]
    z0_mu2 = z-position of microwave 2 [m]
    
    returns:
    probability = probability of being in the target final state
    
    """

    #Define the position of the molecule as a fucntion of time
    r0 = np.array((0, 0, -100e-3))
    v = np.array((0, 0, 200))
    r_t = lambda t: molecule_position(t, r0, v)

    #Define the total time for which the molecule is simulated
    z0 = r0[2]
    vz = v[2]
    T = np.abs(2 * z0 / vz)

    #Define electric field as function of position
    E_r = lambda r: (E_field_ring(r, z0=ring_z1, V=ring_V1) + E_field_ring(
        r, z0=ring_z2, V=ring_V2))

    #Next define electric field as function of time
    E_t = lambda t: E_r(r_t(t))

    #Define the magnetic field
    B_r = lambda r: B_earth
    B_t = lambda t: B_r(r_t(t))

    #Make list of quantum numbers that defines the basis for the matrices
    QN = make_QN(0, 3, 1 / 2, 1 / 2)

    #Get H_0 from file (H_0 should be in rad/s)
    H_0_EB = make_hamiltonian("../utility/TlF_X_state_hamiltonian0to3.py")

    #Make H_0 as function of time
    H_0_t = lambda t: H_0_EB(E_t(t), B_t(t))
    dim = H_0_t(0).shape[0]

    #Fetch the initial state from file
    with open("../utility/initial_state0to3.pickle", 'rb') as f:
        initial_state_approx = pickle.load(f)

    #Fetch the intermediate state from file
    with open("../utility/intermediate_state0to3.pickle", "rb") as f:
        intermediate_state_approx = pickle.load(f)

    #Fetch the final state from file
    with open("../utility/final_state0to3.pickle", 'rb') as f:
        final_state_approx = pickle.load(f)

    #Find the eigenstate of the Hamiltonian that most closely corresponds to initial_state at T=0. This will be used as the
    #actual initial state
    initial_state = find_closest_state(H_0_t(0), initial_state_approx, QN)
    initial_state_vec = initial_state.state_vector(QN)

    #Find the eigenstate of the Hamiltonian that most closely corresponds to final_state_approx at t=T. This will be used to
    #determine what fraction of the molecules end up in the correct final state
    final_state = find_closest_state(H_0_t(T), final_state_approx, QN)
    final_state_vec = final_state.state_vector(QN)

    intermediate_state = find_closest_state(H_0_t(0),
                                            intermediate_state_approx, QN)
    intermediate_state_vec = intermediate_state.state_vector(QN)

    #Find the energies of ini and int so that suitable microwave frequency for mu1 can be calculated
    H_z0 = H_0_EB(E_r(np.array((0, 0, z0_mu1))), B_r(np.array((0, 0, z0_mu1))))
    D_z0, V_z0 = np.linalg.eigh(H_z0)

    ini_index = find_state_idx_from_state(H_z0, initial_state_approx, QN)
    int_index = find_state_idx_from_state(H_z0, intermediate_state_approx, QN)
    fin_index = find_state_idx_from_state(H_z0, final_state_approx, QN)

    #Note: the energies are in 2*pi*[Hz]
    E_ini = D_z0[ini_index]
    E_int = D_z0[int_index]
    omega_mu1 = E_int - E_ini

    #Find the energies of int and fin so that suitable microwave frequency for mu2 can be calculated
    H_z0 = H_0_EB(E_r(np.array((0, 0, z0_mu2))), B_r(np.array((0, 0, z0_mu2))))
    D_z0, V_z0 = np.linalg.eigh(H_z0)

    ini_index = find_state_idx_from_state(H_z0, initial_state_approx, QN)
    int_index = find_state_idx_from_state(H_z0, intermediate_state_approx, QN)
    fin_index = find_state_idx_from_state(H_z0, final_state_approx, QN)

    #Note: the energies are in 2*pi*[Hz]
    E_int = D_z0[int_index]
    E_fin = D_z0[fin_index]
    omega_mu2 = E_fin - E_int

    #Define dipole moment of TlF
    D_TlF = 2 * np.pi * 4.2282 * 0.393430307 * 5.291772e-9 / 4.135667e-15  # [rad/s/(V/cm)]

    #Calculate the approximate power required for each set of microwaves to get a specified peak Rabi rate for the transitions
    ME1 = np.abs(
        calculate_microwave_ED_matrix_element_mixed_state_uncoupled(
            initial_state_approx, intermediate_state_approx, reduced=False))

    ME2 = np.abs(
        calculate_microwave_ED_matrix_element_mixed_state_uncoupled(
            intermediate_state_approx, final_state_approx, reduced=False))

    P1 = calculate_power_needed(Omega1, ME1)
    P2 = calculate_power_needed(Omega2, ME2)

    #Define the microwave electric field as a function of time
    E_mu1_t = lambda t: microwave_field(
        r_t(t), power=P1, z0=z0_mu1, fwhm=1.1 * 0.0254)
    E_mu2_t = lambda t: microwave_field(
        r_t(t), power=P2, z0=z0_mu2, fwhm=1.1 * 0.0254)

    #Define matrix for microwaves coupling J = 0 to 1
    J1_mu1 = 0
    J2_mu1 = 1
    omega_mu1 = omega_mu1 + Delta
    H1 = make_H_mu(J1_mu1, J2_mu1, omega_mu1, QN)
    H_mu1 = lambda t: H1(0) * D_TlF * E_mu1_t(t)

    #Define matrix for microwaves coupling J = 1 to 2
    J1_mu2 = 1
    J2_mu2 = 2
    omega_mu2 = omega_mu2 + delta - Delta
    H2 = make_H_mu(J1_mu2, J2_mu2, omega_mu2, QN)
    H_mu2 = lambda t: H2(0) * D_TlF * E_mu2_t(t)

    #Make the matrices used to transform to rotating frame
    U1, D1 = make_transform_matrix(J1_mu1, J2_mu1, omega_mu1, QN)
    U2, D2 = make_transform_matrix(J1_mu2, J2_mu2, omega_mu2 + omega_mu1, QN)

    U = lambda t: U1(t) @ U2(t)
    D = lambda t: D1 + D2

    #Define number of timesteps and make a time-array
    t_array = np.linspace(0, T, N_steps)

    #Calculate timestep
    dt = T / N_steps

    #Set system to its initial state
    psi = initial_state_vec

    #Loop over timesteps to evolve system in time
    for i, t in enumerate(t_array):
        #Calculate the necessary Hamiltonians at this time
        H_0 = H_0_t(t)
        H_mu1_i = H_mu1(t)
        H_mu2_i = H_mu2(t)

        #Diagonalize H_0 and transform to that basis
        D_0, V_0, info_0 = zheevd(H_0)
        if info_0 != 0:
            print("zheevd didn't work for H_0")
            D_0, V_0 = np.linalg.eigh(H_0)
        #Make intermediate hamiltonian by transforming H to the basis where H_0 is diagonal
        H_I = V_0.conj().T @ H_0 @ V_0

        #Sort the eigenvalues so they are in ascending order
        index = np.argsort(D_0)
        D_0 = D_0[index]
        V_0 = V_0[:, index]

        #Find the microwave coupling matrix:
        H_mu1_i = V_0.conj().T @ H_mu1_i @ V_0 * np.exp(1j * omega_mu1 * t)
        H_mu1_i = block_diag(H_mu1_i[0:16, 0:16], np.zeros(
            (dim - 16, dim - 16)))
        H_mu1_i = np.triu(H_mu1_i) + np.triu(
            H_mu1_i).conj().T  #+ np.diag(np.diag(H1))

        H_mu2_i = V_0.conj().T @ H_mu2_i @ V_0 * np.exp(1j * omega_mu2 * t)
        H_mu2_i = block_diag(np.zeros((4, 4)), H_mu2_i[4:36, 4:36],
                             np.zeros((dim - 36, dim - 36)))
        H_mu2_i = np.triu(H_mu2_i) + np.triu(
            H_mu2_i).conj().T  #+ np.diag(np.diag(H1))

        #Make total hamiltonian
        H_I = H_I + H_mu1_i + H_mu2_i

        #Find transformation matrices for rotating basis
        U_t = U(t)
        D_t = D(t)

        #Transform H_I to the rotating basis
        H_R = U_t.conj().T @ H_I @ U_t + D_t

        #Diagonalize H_R
        D_R, V_R, info_R = zheevd(H_R)
        if info_R != 0:
            print("zheevd didn't work for H_R")
            D_R, V_R = np.linalg.eigh(H_R)

        #Propagate state vector in time
        psi = V_0 @ V_R @ np.diag(np.exp(
            -1j * D_R * dt)) @ V_R.conj().T @ V_0.conj().T @ psi

    psi_fin = vector_to_state(psi, QN)

    #Calculate overlap between final target state and psi
    overlap = final_state_vec.conj().T @ U(T) @ psi
    probability = np.abs(overlap)**2

    return probability
Exemple #7
0
def neumann(d, rho):
    import scipy.linalg.lapack as lapak
    b = lapak.zheevd(rho)
    VnE = shannon(d, b[0])
    return VnE
Exemple #8
0
def neumann(d, rho):
    # Returns the von Neumann entropy of a dxd density matrix rho
    import scipy.linalg.lapack as lapak
    b = lapak.zheevd(rho)
    VnE = shannon(d, b[0])
    return VnE
Exemple #9
0
def bdsCorr():
    from numpy import zeros
    from math import acos, sqrt
    c1 = -0.9
    c2 = -0.8
    c3 = -0.8
    from states import rho_bds
    rho = zeros((4, 4), dtype=complex)
    rho = rho_bds(c1, c2, c3)
    eig = lapak.zheevd(rho)
    print('eigens:', eig[0][0], eig[0][1], eig[0][2], eig[0][3])
    import discord
    dp = 0.05
    d = 20 * (1 - 0)
    di = zeros(d)
    cc = zeros(d)
    mi = zeros(d)
    diE = zeros(d)
    ccE = zeros(d)
    miE = zeros(d)
    rhopE = zeros((4, 4), dtype=complex)
    pv = zeros(d)
    rhop = zeros((4, 4), dtype=complex)
    import kraus
    import tomography as tomo
    p = -dp
    for j in range(0, d):
        p = p + dp
        # rhop = kraus.rho_pd(p, rho)  # ; print(rhop) # teste para ver a cara do rhop
        c1p = c1 * (1.0 - p)**2
        c2p = c2 * (1.0 - p)**2
        c3p = c3
        print("p = ", p, ", c1p=", c1p, ", c2p=", c2p, ", c3p=", c3p)
        p00 = (1.0 + c1p - c2p + c3p) / 4.0
        p01 = (1.0 + c1p + c2p - c3p) / 4.0
        p10 = (1.0 - c1p + c2p + c3p) / 4.0
        p11 = (1.0 - c1p - c2p - c3p) / 4.0
        print("p00 = ", p00, ", p01=", p01, ", p10=", p10, ", p11=", p11)
        theta = 2.0 * acos(sqrt(p00 + p01))
        alpha = 2.0 * acos(sqrt(p00 + p10))
        print("theta = ", theta, ", alpha", alpha)
        print("")
        rhop = rho_bds(c1p, c2p, c3p)
        pv[j] = p
        di[j] = discord.discord_oz_bds(rhop)
        cc[j] = discord.ccorr_hv_bds(rhop)
        mi[j] = discord.mi_bds(rhop)
        '''sj = str(j)
        path1 = '/home/jonasmaziero/Dropbox/Research/IBM_QC/'
        path2 = 'tomography/BDS/bell_diagonal/'
        path = path1 + path2 + sj + '/'
        rhopE = tomo.tomo_2qb(path)
        diE[j] = discord.discord_oz_bds(rhopE)
        ccE[j] = discord.ccorr_hv_bds(rhopE)
        miE[j] = discord.mi_bds(rhopE)
        eigE = lapak.zheevd(rhopE)
        print('eigensE:', eigE[0][0], eigE[0][1], eigE[0][2], eigE[0][3])
        print('di =', di[j], '  diE = ', diE[j])'''

    plt.plot(pv, di, label='di')
    plt.plot(pv, cc, label='cc')
    plt.plot(pv, mi, label='im')
    plt.xlabel('p')
    plt.legend()
    plt.show()