Esempio n. 1
0
def realization(H0, basis, psi_i, w, I, start, stop, num, endpoint, i):
    print i
    disorder = [[np.random.uniform(-w, w), i] for i in range(L)]
    Hl = hamiltonian([["n", disorder]], [],
                     basis=H0.basis,
                     dtype=np.float32,
                     check_pcon=False,
                     check_herm=False,
                     check_symm=False)
    expH = exp_op(H0 + Hl,
                  a=-1j,
                  start=start,
                  stop=stop,
                  num=num,
                  endpoint=endpoint,
                  iterate=True)

    times = expH.grid

    psi_t = expH.dot(psi_i)
    obs = obs_vs_time(
        psi_t, times, {"I": I},
        basis=basis)  #,Sent_args=dict(sparse=True,sub_sys_A=[0]))

    try:
        return obs["I"], obs["Sent_time"]["Sent"]
    except KeyError:
        return obs["I"]
Esempio n. 2
0
def Unitaries(delta_time,
              L,
              J,
              hz,
              action_min,
              var_max,
              var_min,
              state_i,
              save=False,
              save_str=''):

    # define Hamiltonian
    b = 0.0
    lin_fun = lambda t: b
    H = Hamiltonian(L, fun=lin_fun, **{'J': J, 'hz': hz})

    # number of unitaries
    n = int((var_max - var_min) / action_min)

    # preallocate dict
    expm_dict = {}
    for i in range(n + 1):
        # define matrix exponential; will be changed every time b is overwritten
        b = state_i[0] + i * action_min
        expm_dict[i] = np.asarray(
            exp_op(H, a=-1j * delta_time).get_mat().todense())

    # calculate eigenbasis of H_target
    b = +2.0
    _, V_target = H.eigh()

    if save:

        ### define save directory for data
        # read in local directory path
        str1 = os.getcwd()
        str2 = str1.split('\\')
        n = len(str2)
        my_dir = str2[n - 1]
        # create directory if non-existant
        save_dir = my_dir + "/unitaries"
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
        save_dir = "unitaries/"

        # save file
        dataname = save_dir + "unitaries_L={}".format(L) + save_str + '.pkl'
        cPickle.dump(expm_dict, open(dataname, "wb"))

        dataname = save_dir + "target_basis_L={}".format(L) + save_str + '.pkl'
        cPickle.dump(V_target, open(dataname, "wb"))

    else:
        return expm_dict
Esempio n. 3
0
def precompute_expmatrix(param_SA, h_set, H):
    """

    Purpose:
        Precomputes the evolution matrix and stores them in a global dictionary
        If unitary.dat is available, reads the matrices from this file

    """

    L = param_SA['L']
    J = param_SA['J']
    hz = param_SA['hz']
    hx_final_state = param_SA['hx_final_state']
    delta_t = param_SA['delta_t']

    import os.path
    from scipy.linalg import expm
    global matrix_dict
    file_name = ut.make_unitary_file_name(param_SA).replace(
        "SA", "unitaries/unitary")
    file_eigenvector = ut.make_unitary_file_name(param_SA).replace(
        "SA", "unitaries/eigenvector_FS")

    if os.path.isfile(file_name):
        with open(file_name, "rb") as f:
            matrix_dict = pickle.load(f)
            f.close()
        with open(file_eigenvector, "rb") as f:
            param_SA['V_target'] = pickle.load(f)
    else:
        matrix_dict = {}
        hx_dis_init = hx_discrete[0]
        for h in h_set:
            hx_discrete[0] = h  #  fix it later !
            matrix_dict[h] = np.asarray(
                exp_op(H, a=-1j * delta_t).get_mat().todense())

        # define matrix exponential
        # calculate final basis

        hx_discrete[0] = hx_final_state
        _, V_target = H.eigh()
        param_SA['V_target'] = V_target

        with open(file_eigenvector, "wb") as f:
            pickle.dump(V_target, f)
            f.close()

        hx_discrete[0] = hx_dis_init  # resetting to it's original value
        with open(file_name, "wb") as f:
            pickle.dump(matrix_dict, f)
Esempio n. 4
0
def realization(H_Heis, psi_0, basis, diag_op, times, real):
    """
        This function computes the entropies for a single disorder realisation.
        --- arguments ---
        vs: vector of ramp speeds
        H_Heis: static Heisenberg Hamiltonian
        basis: spin_basis_1d object containing the spin basis
        n_real: number of disorder realisations; used only for timing
        """
    ti = time()  # get start time
    #
    seed()  # the random number needs to be seeded for each parallel process
    #
    # draw random field uniformly from [-1.0,1.0] for each lattice site
    unscaled_fields = -1 + 2 * ranf((basis.L, ))
    # define z-field operator site-coupling list
    h_z = [[unscaled_fields[i], i] for i in range(basis.L)]
    # static list
    disorder_field = [["z", h_z]]
    # compute disordered z-field Hamiltonian
    no_checks = {"check_herm": False, "check_pcon": False, "check_symm": False}
    Hz = hamiltonian(disorder_field, [],
                     basis=basis,
                     dtype=np.float64,
                     **no_checks)
    # compute the MBL and ETH Hamiltonians for the same disorder realisation
    H_MBL = H_Heis + h_MBL * Hz
    #
    expO = exp_op(H_MBL)
    psi_t = psi_0
    time_old = 0
    imb = []
    #        Sent=[]
    #        sub_sizes=[1,2,3]
    for a_time in times:
        expO.set_a(-1j * (a_time - time_old))
        time_old = a_time
        psi_t = expO.dot(psi_t)
        imb.append(np.einsum('i,i,i', np.conj(psi_t), diag_op, psi_t))
#                Sent.append([map(lambda x: ent_entropy(psi_t,basis,chain_subsys=range(x,x+size))["Sent"],range(basis.L-size+1)) for size in sub_sizes])
#       imb_at_t = lambda time: diag_op_exp(expO,psi_0,diag_op,time)
#       imb = list(map(imb_at_t,times))
#       imb = list(map(imb_at_t,times))
# show time taken
    print("realization {0}/{1} took {2:.2f} sec".format(
        real + 1, n_real,
        time() - ti))
    #
    return np.real(imb)
Esempio n. 5
0
def Fidelity(psi_i,H,N_time_step,delta_t,psi_target,option='standard'):
    """
    Purpose:
        Calculates final fidelity by evolving psi_i over a N_time_step 
    Return: 
        Norm squared between the target state psi_target and the evolved state (according to the full hx_discrete protocol)
        
    """
    if option is 'standard':
        psi_evolve=psi_i.copy()
        for t in range(N_time_step):
            psi_evolve = exp_op(H(time=t),a=-1j*delta_t).dot(psi_evolve)
        
        return abs(np.sum(np.conj(psi_evolve)*psi_target))**2
    else:
        return fast_Fidelity(psi_i,H,N_time_step,delta_t,psi_target)
Esempio n. 6
0
def real(H_dict,I,psi_0,w,t,i):
	# body of function goes below
	ti = time() # start timing function for duration of reach realisation
	# create a parameter list which specifies the onsite potential with disorder
	params_dict=dict(H0=1.0)
	for j in range(L):
		params_dict["n"+str(j)] = uniform(-w,w)
	# using the parameters dictionary construct a hamiltonian object with those
	# parameters defined in the list
	H = H_dict.tohamiltonian(params_dict)
	# use exp_op to get the evolution operator
	U = exp_op(H,a=-1j,start=t.min(),stop=t.max(),num=len(t),iterate=True)
	psi_t = U.dot(psi_0) # get generator psi_t for time evolved state
	# use obs_vs_time to evaluate the dynamics
	t = U.grid # extract time grid stored in U, and defined in exp_op
	obs_t = obs_vs_time(psi_t,t,dict(I=I))
	# print reporting the computation time for realization
	print("realization {}/{} completed in {:.2f} s".format(i+1,n_real,time()-ti))
	# return observable values
	return obs_t["I"]
Esempio n. 7
0
def Fidelity(psi_i,
             H_fid,
             t_vals,
             delta_t,
             psi_f=None,
             all_obs=False,
             Vf=None):
    ''' This function calculates the physical quantities given a time-dep Hamiltonian H_fid.
		If psi_f is not given, then it returns the fidelity in the instantaneous eigenstate, otherwise
		--- the fidelity in the final state. '''
    basis = H_fid.basis

    # evolve state
    #psi_t = H_fid.evolve(psi_i,t_vals[0],t_vals,iterate=True,atol=1E-12,rtol=1E-12)

    # fidelity
    fid = []
    if all_obs:
        # get sysstem size
        L = basis.L
        # entanglement entropy density
        Sent = []
        subsys = [j for j in range(L / 2)]
        # energy
        E = []
        # energy fluctuations
        dE = []
        Sd = []

    psi = psi_i.copy()
    for i, t_i in enumerate(t_vals):
        #for i, psi in enumerate(psi_t):

        psi = exp_op(H_fid(time=t_i), a=-1j * delta_t).dot(psi)

        if psi_f is not None:
            # calculate w.r.t. final state
            psi_target = psi_f
        else:
            # calculate w.r.t. instantaneous state
            _, psi_inst = H_fid.eigsh(time=t_vals[i], k=1, sigma=-100.0)
            psi_target = psi_inst.squeeze()

        fid.append(abs(psi.conj().dot(psi_target))**2)

        #print i, abs(psi.conj().dot(psi_target))**2

        if all_obs:

            if L > 1:
                EGS, _ = H_fid.eigsh(time=t_vals[i],
                                     k=2,
                                     which='BE',
                                     maxiter=1E10,
                                     return_eigenvectors=False)
            else:
                EGS = H_fid.eigvalsh(time=t_vals[i])[0]

            E.append(
                H_fid.matrix_ele(psi, psi, time=t_vals[i]).real / L - EGS / L)
            if i == 0:
                dE.append(0.0)
            else:
                dE.append(
                    np.sqrt((H_fid * H_fid(time=t_vals[i])).matrix_ele(
                        psi, psi, time=t_vals[i]).real / L**2 - E[i]**2))
            #print  H_fid2.matrix_ele(psi,psi,time=t_vals[i]).real/L**2 - E[i]**2

            pn = abs(Vf.conj().T.dot(psi))**2.0 + np.finfo(psi[0].dtype).eps
            Sd.append(-pn.dot(np.log(pn)) / L)

            if basis.L != 1:
                Sent.append(
                    ent_entropy(psi, basis, chain_subsys=subsys)['Sent'])
            else:
                Sent.append(float('nan'))

    if not all_obs:
        return fid
    else:
        return fid, E, dE, Sent, Sd
Esempio n. 8
0
def Q_learning(RL_params,
               physics_params,
               theta=None,
               tilings=None,
               greedy=False):

    ####################################################################
    start_time = time.time()
    ####################################################################
    # display full strings
    np.set_printoptions(threshold='nan')
    ######################################################################
    #######################   read off params 	 #########################
    ######################################################################

    # read off RL_params
    RL_keys = [
        'N_episodes', 'alpha_0', 'eta', 'lmbda', 'beta_RL', 'traces', 'dims',
        'N_tiles', 'state_i', 'h_field', 'dh_field'
    ]
    from numpy import array
    for key, value in RL_params.iteritems():
        #print key, repr(value)
        if key not in RL_keys:
            raise TypeError(
                "Key '{}' not allowed for use in dictionary!".format(key))
        # turn key to variable and assign its value
        exec("{} = {}".format(key, repr(value))) in locals()

    # read off physics params
    physics_keys = [
        'L', 'max_t_steps', 'delta_t', 'J', 'hz', 'hx_i', 'hx_f', 'psi_i',
        'psi_f', 'E_i', 'E_f'
    ]
    for key, value in physics_params.iteritems():
        #print key, repr(value)
        if key not in physics_keys:
            raise TypeError(
                "Key '{}' not allowed for use in dictionary!".format(key))
        # turn key to variable and assign its value
        exec("{} = {}".format(key, repr(value))) in locals()

    ######################################################################

    # define all actions
    actions = RL.all_actions()

    # eta limits # max and min field
    hx_limits = [h_field[0], h_field[-1]]

    # get dimensions
    N_tilings, N_lintiles, N_vars = dims
    N_tiles = N_lintiles**N_vars
    N_actions = len(actions)
    shift_tile_inds = [j * N_tiles for j in xrange(N_tilings)]

    if theta is None:
        theta = np.zeros((N_tiles * N_tilings, max_t_steps, N_actions),
                         dtype=np.float64)

    if tilings is None:
        tilings = RL.gen_tilings(h_field, dh_field, N_tilings)

    # pre-allocate traces variable
    e = np.zeros_like(theta)
    fire_trace = np.ones(N_tilings)

    if not greedy:
        # pre-allocate usage vector: inverse gradient descent learning rate
        u0 = 1.0 / alpha_0 * np.ones((N_tiles * N_tilings, ), dtype=np.float64)
    else:
        u0 = np.inf * np.ones((N_tiles * N_tilings, ), dtype=np.float64)
    u = np.zeros_like(u0)

    #### physical quantities

    # define ED Hamiltonian H(t)
    b = hx_i
    lin_fun = lambda t: b  #+ m*t
    # define Hamiltonian
    H = Hamiltonian.Hamiltonian(L, fun=lin_fun, **{'J': J, 'hz': hz})
    # define matrix exponential
    exp_H = exp_op(H, a=-1j * delta_t)
    #"""
    ''' will not need onless we plot '''
    # defien Hamiltonian for any step-lie protocol p_vals at times t_vals
    t_vals, p_vals = [0.0, 0.0], [0.0, 0.0]

    def step_protocol(t):
        return p_vals[np.argmin(abs(np.asarray(t_vals) - t))]

    H_fid = Hamiltonian.Hamiltonian(L, fun=step_protocol, **{'J': J, 'hz': hz})
    # calculate final basis
    b = hx_f
    _, Vf = H.eigh(time=0.0)
    b = hx_i
    ''' will not need '''
    #"""

    # average reward
    Return_ave = np.zeros((N_episodes, 1), dtype=np.float64)
    Return = Return_ave.copy()
    Fidelity_ep = Return_ave.copy()

    # initialise best fidelity
    best_fidelity = 0.0  # best encountered fidelity
    # set of actions for best encountered protocol
    best_actions = [random.choice(actions) for j in range(max_t_steps)]

    # calculate importance sampling ratio
    R = 0.0  # instantaneous fidelity

    psi = np.zeros_like(psi_i)

    # loop over episodes
    for ep in xrange(N_episodes):
        # set traces to zero
        e *= 0.0
        # set initial usage vector
        u[:] = u0[:]

        # set initial state of episode
        S = state_i.copy()

        # get set of features present in S
        theta_inds = RL.find_feature_inds(S, tilings, shift_tile_inds)
        Q = np.sum(theta[theta_inds, 0, :],
                   axis=0)  # for each action at time t_step=0

        # preallocate physical quantties
        psi[:] = psi_i[:]  # quantum state at time

        protocol_inst = []
        t_inst = []

        # calculate fidelity for each fixed episode
        Return_ep = 0.0

        # taken encountered and taken
        actions_taken = []

        # generate episode
        for t_step in xrange(max_t_steps):  #

            # calculate available actions from state S
            avail_inds = np.argwhere(
                (S[0] + np.array(actions) <= hx_limits[1]) *
                (S[0] + np.array(actions) >= hx_limits[0])).squeeze()
            avail_actions = [actions[_j] for _j in avail_inds]

            # calculate greedy action(s) wrt Q policy
            A_greedy = avail_actions[random.choice(
                np.argwhere(Q[avail_inds] == np.amax(Q[avail_inds])).ravel())]

            # choose a random action
            P = np.exp(beta_RL * Q[avail_inds])
            p = np.cumsum(P / sum(P))
            if greedy or beta_RL > 1E12:
                A = A_greedy
            else:
                A = avail_actions[np.searchsorted(p, random.uniform(0.0, 1.0))]

            # find the index of A
            indA = actions.index(A)

            # reset traces if A is exploratory
            if abs(A - A_greedy) > np.finfo(A).eps:
                e *= 0.0

            # take action A, return state S_prime and actual reward R
            ################################################################################
            ######################    INTERACT WITH ENVIRONMENT    #########################
            ################################################################################

            # define new state
            S_prime = S.copy()
            # calculate new field value
            S_prime[0] += A

            ### assign reward
            R *= 0.0

            # all physics happens here
            # update dynamic arguments in place: ramp = m*t+b

            b = S_prime[0]
            psi = exp_H.dot(psi)

            # assign reward
            if t_step == max_t_steps - 1:
                # calculate final fidelity
                fidelity = abs(psi.conj().dot(psi_f))**2
                # reward
                R += fidelity

            ################################################################################
            ################################################################################
            ################################################################################

            # update episodic return
            Return_ep += R

            # update protocol and time
            protocol_inst.append(S_prime[0])
            t_inst.append(t_step * delta_t)

            # record action taken
            actions_taken.append(A)

            ############################

            # calculate usage and alpha vectors: alpha_inf = eta
            u[theta_inds] *= (1.0 - eta)
            u[theta_inds] += 1.0
            alpha = 1.0 / (N_tilings * u[theta_inds])

            # Q learning update rule; GD error in time t
            delta = R - Q[indA]  # error in gradient descent
            # TO
            Q_old = theta[theta_inds, t_step, indA].sum()

            # update traces
            e[theta_inds, t_step, indA] = alpha * fire_trace

            # check if S_prime is terminal or went out of grid
            if t_step == max_t_steps - 1:
                # update theta
                theta += delta * e
                # GD error in field h
                delta_TO = Q_old - theta[theta_inds, t_step, indA].sum()
                theta[theta_inds, t_step, indA] += alpha * delta_TO
                # go to next episode
                break

            # get set of features present in S_prime
            theta_inds_prime = RL.find_feature_inds(S_prime, tilings,
                                                    shift_tile_inds)

            # t-dependent Watkin's Q learning
            Q = np.sum(theta[theta_inds_prime, t_step + 1, :], axis=0)

            # update theta
            delta += max(Q)
            theta += delta * e

            # GD error in field h
            delta_TO = Q_old - theta[theta_inds, t_step, indA].sum()
            theta[theta_inds, t_step, indA] += alpha * delta_TO

            # update traces
            e[theta_inds, t_step,
              indA] -= alpha * e[theta_inds, t_step, indA].sum()
            e *= lmbda

            ################################
            # S <- S_prime
            S[:] = S_prime[:]
            theta_inds[:] = theta_inds_prime[:]

        if greedy:
            return protocol_inst, t_inst

        # save average return
        Return_ave[ep] = 1.0 / (ep + 1) * (Return_ep + ep * Return_ave[ep - 1])
        Return[ep] = Return_ep
        Fidelity_ep[ep] = fidelity

        # if greedy policy completes a full episode and if greedy fidelity is worse than inst one
        if fidelity - best_fidelity > 1E-12:
            # update list of best actions
            best_actions[:] = actions_taken[:]
            # calculate best protocol and fidelity
            protocol_best, t_best = best_protocol(best_actions, hx_i, delta_t)

            R_best = R
            best_fidelity = fidelity

            theta = Learn_Policy(state_i, theta, tilings, dims, best_actions,
                                 R_best)
            #theta = Replay(50,RL_params,physics_params,theta,tilings,best_actions,R_best)

        # force-learn best encountered every 100 episodes
        if (ep % 40 == 0 and ep != 0) and (R_best
                                           is not None) and beta_RL < 1E12:
            print 'learned best encountered'
            theta = Learn_Policy(state_i, theta, tilings, dims, best_actions,
                                 R_best)
            #theta = Replay(50,RL_params,physics_params,theta,tilings,best_actions,R_best)

        #'''
        if ep % 20 == 0:
            print "finished simulating episode {} with fidelity {} at hx_f = {}.".format(
                ep + 1, np.round(fidelity, 3), S_prime[0])
            print 'best encountered fidelity is {}.'.format(
                np.round(best_fidelity, 3))
        #'''

        #'''
        # plot protocols and learning rate
        if (ep % 500 == 0 and ep != 0) or (np.round(fidelity, 3) == 1.0):

            RL_params['beta_RL'] = 1E12
            RL_params['lmbda'] = 0.0
            RL_params['alpha_0'] = 0.0

            # fig file name params
            save = False  #True
            save_vars = ['J', 'hz', 'hxi', 'hxf', 'Ei', 'Ef', 'Neps']
            save_vals = truncate([J, hz, hx_i, hx_f, E_i / L, E_f / L, j], 2)
            save_params = "_L={}".format(L) + "".join(
                ['_' + i + '=' + k for i, k in zip(save_vars, save_vals)])

            # calculate greedy fidelity
            Q_args = (RL_params, physics_params)
            Q_kwargs = {'theta': theta, 'tilings': tilings}
            protocol_greedy, t_greedy = Q_learning(*Q_args,
                                                   greedy=True,
                                                   **Q_kwargs)

            # calculate inst fidelities of interpolated protocols
            t_vals, p_vals = t_inst, protocol_inst
            F_inst, E_inst, dE_inst, Sent_inst, Sd_inst = Fidelity(
                psi_i,
                H_fid,
                t_vals,
                delta_t,
                psi_f=psi_f,
                all_obs=True,
                Vf=Vf)

            t_vals, p_vals = t_greedy, protocol_greedy
            F_greedy, E_greedy, dE_greedy, Sent_greedy, Sd_greedy = Fidelity(
                psi_i,
                H_fid,
                t_vals,
                delta_t,
                psi_f=psi_f,
                all_obs=True,
                Vf=Vf)

            t_vals, p_vals = t_best, protocol_best
            F_best, E_best, dE_best, Sent_best, Sd_best = Fidelity(
                psi_i,
                H_fid,
                t_vals,
                delta_t,
                psi_f=psi_f,
                all_obs=True,
                Vf=Vf)

            # prepare plot data
            times = [t_inst, t_greedy, t_best]
            protocols = [protocol_inst, protocol_greedy, protocol_best]
            fidelities = [F_inst, F_greedy, F_best]
            energies = [E_inst, E_greedy, E_best]
            d_energies = [dE_inst, dE_greedy, dE_best]
            s_ents = [Sent_inst, Sent_greedy, Sent_best]
            s_ds = [Sd_inst, Sd_greedy, Sd_best]

            Data = np.zeros((7, max_t_steps))
            Data[0, :] = t_best
            Data[1, :] = protocol_best
            Data[2, :] = F_best
            Data[3, :] = E_best
            Data[4, :] = dE_best
            Data[5, :] = Sent_best
            Data[6, :] = Sd_best

            # plot data
            user_input = raw_input("continue? (y or n) ")
            if user_input == 'y':
                # plot rewards
                #plot_rewards(N_episodes,Return_ave,Return,Fidelity_ep,'rewards',save_params,save)
                # plot protocols
                plot_protocols(times, protocols, fidelities, 'fidelity',
                               save_params, save)
                #plot_protocols(times,protocols,energies,'energy',save_params,save)
                #plot_protocols(times,protocols,d_energies,'energy fluct.',save_params,save)
                #plot_protocols(times,protocols,s_ents,'ent. entropy',save_params,save)
                #plot_protocols(times,protocols,s_ds,'diag. entropy',save_params,save)
                """		
				# calculate approximate Q function
				etas = np.linspace(hx_limits[0],hx_limits[1],101)
				#etas = np.linspace(-1.0,1.0,101)
				Q_plot = RL.Q_greedy(etas,theta,tilings,shift_tile_inds,max_t_steps).T
				
				plot_Q(etas,t_best,-Q_plot,'Q_fn',save_params,save)
				"""

                if save:
                    user_input = raw_input("save data? (y or n) ")
                    if user_input == 'y':
                        args = (L, ) + tuple(np.around([J, hz, hx_i, hx_f], 2))
                        dataname = "best_L=%s_J=%s_hz=%s_hxi=%s_hxf=%s.txt" % args
                        np.savetxt(dataname, Data.T)

            RL_params['beta_RL'] = beta_RL
            RL_params['lmbda'] = lmbda
            RL_params['alpha_0'] = alpha_0
        #'''

    print "Calculating the Q function loop using Q-Learning took", (
        "--- %s seconds ---" % (time.time() - start_time))
Esempio n. 9
0
n_1=hamiltonian(n_1_static,[],basis=basis,dtype=np.float64,
				check_herm=False,check_pcon=False)
# construct operator n_2 = $n_{j=L/2}$
n_2_static=[['n',[[1.0,L//2]]]]
n_2=hamiltonian(n_2_static,[],basis=basis,dtype=np.float64,
				check_herm=False,check_pcon=False)
# transform n_j operators to momentum space
n_1=n_1.rotate_by(FT,generator=False)
n_2=n_2.rotate_by(FT,generator=False)
##### evaluate nonequal time correlator <FS|n_2(t) n_1(0)|FS> #####
# define time vector
t=np.linspace(0.0,90.0,901)
# calcualte state acted on by n_1
n_psi0=n_1.dot(psi0)
# construct time-evolution operator using exp_op class (sometimes faster)
U = exp_op(Hblock,a=-1j,start=t.min(),stop=t.max(),num=len(t),iterate=True)
# evolve states
psi_t=U.dot(psi0)
n_psi_t = U.dot(n_psi0)
# alternative method for time evolution using Hamiltonian class
#psi_t=Hblock.evolve(psi0,0.0,t,iterate=True)
#n_psi_t=Hblock.evolve(n_psi0,0.0,t,iterate=True)
# preallocate variable
correlators=np.zeros(t.shape+psi0.shape[1:])
# loop over the time-evolved states
for i, (psi,n_psi) in enumerate( zip(psi_t,n_psi_t) ):
	correlators[i,:]=n_2.matrix_ele(psi,n_psi,diagonal=True).real
# evaluate correlator at finite temperature
n_FD=1.0/(np.exp(beta*E)+1.0)
correlator = (n_FD*correlators).sum(axis=-1)
##### plot spectra
Esempio n. 10
0
w = 0.0
t = -1.0 * np.exp(-1j * a * np.pi)

J = [[t, i, (i + 1) % L] for i in range(L - 1)]
J_cc = [[t.conjugate(), i, (i + 1) % L] for i in range(L - 1)]
V = [[np.random.uniform(-w, w) + 0.01 * i, i] for i in range(L - 1)]
static = [["+-", J], ["-+", J_cc], ["n", V]]

H = hamiltonian(static, [], basis=basis)

sites = np.arange(L)

psi = np.exp(-(sites - L / 4)**2 / float(L / 10))
psi /= np.linalg.norm(psi)

psi_t = exp_op(H, a=-1j, start=0, stop=1000000, num=100000,
               iterate=True).dot(psi)

psi = next(psi_t)
ns = np.abs(psi)**2

fig = plt.figure()
ax = plt.gca()
line, = ax.plot(sites, ns, marker="")


def updatefig(i):
    psi = next(psi_t)
    ns = np.abs(psi)**2
    line.set_data(sites, ns)

    return line,
Esempio n. 11
0
#
###### calculate initial states ######
# calculating bandwidth for non-driven hamiltonian
[E_1d_min], psi_1d = Hzz_1d.eigsh(k=1, which="SA")
[E_2d_min], psi_2d = Hzz_2d.eigsh(k=1, which="SA")
# setting up initial states
psi0_1d = psi_1d.ravel()
psi0_2d = psi_2d.ravel()
#
###### time evolution ######
# stroboscopic time vector
nT = 200  # number of periods to evolve to
t = Floquet_t_vec(Omega, nT,
                  len_T=1)  # t.vals=t, t.i=initial time, t.T=drive period
# creating generators of time evolution using exp_op class
U1_1d = exp_op(Hzz_1d + A * Hx_1d, a=-1j * t.T / 4)
U2_1d = exp_op(Hzz_1d - A * Hx_1d, a=-1j * t.T / 2)
U1_2d = exp_op(Hzz_2d + A * Hx_2d, a=-1j * t.T / 4)
U2_2d = exp_op(Hzz_2d - A * Hx_2d, a=-1j * t.T / 2)


# user-defined generator for stroboscopic dynamics
def evolve_gen(psi0, nT, *U_list):
    yield psi0
    for i in range(nT):  # loop over number of periods
        for U in U_list:  # loop over unitaries
            psi0 = U.dot(psi0)
        yield psi0


# get generator objects for time-evolved states
Esempio n. 12
0
def test():
    L = 5

    start = 0
    stop = 10
    num = 10

    J = [[1.0, i, (i + 1) % L] for i in range(L)]
    h = [[1.0, i] for i in range(L)]

    static = [["xx", J], ["yy", J], ["zz", J]]
    dynamic = [["z", h, np.sin, ()]]

    blocks = []

    for Nup in range(L + 1):
        blocks.append({"Nup": Nup})

    H_block = block_diag_hamiltonian(blocks, static, dynamic, spin_basis_1d,
                                     (L, ), np.float64)
    H = hamiltonian(static, dynamic, N=L)

    for t in np.linspace(0, 2 * np.pi):
        E = H.eigvalsh(time=t)
        E_blocks = H.eigvalsh(time=t)
        np.testing.assert_allclose(E, E_blocks)

    static = [["zz", J]]
    dynamic = [["x", h, f, []]]

    blocks = []
    for kblock in range(L):
        blocks.append({"kblock": kblock})

    H = hamiltonian(static, dynamic, N=L)

    [E0] = H.eigsh(time=0.3, k=1, which='SA', return_eigenvectors=False)

    block_op = block_ops(blocks,
                         static,
                         dynamic,
                         spin_basis_1d, (L, ),
                         np.complex128,
                         compute_all_blocks=True)

    # real time.
    expH = exp_op(H,
                  a=-1j,
                  start=start,
                  stop=stop,
                  iterate=True,
                  num=num,
                  endpoint=True)

    times = np.linspace(start, stop, num=num, endpoint=True)

    psi0 = np.random.ranf(H.Ns)
    psi0 /= np.linalg.norm(psi0)

    psi_exact_1 = H.evolve(psi0,
                           0,
                           times,
                           iterate=True,
                           atol=1e-15,
                           rtol=1e-15)
    psi_block_1 = block_op.evolve(psi0,
                                  0,
                                  times,
                                  iterate=True,
                                  atol=1e-15,
                                  rtol=1e-15,
                                  n_jobs=4)

    psi_exact_2 = expH.dot(psi0, time=0.3)
    psi_block_2 = block_op.expm(psi0,
                                H_time_eval=0.3,
                                start=start,
                                stop=stop,
                                iterate=True,
                                num=num,
                                endpoint=True,
                                n_jobs=2,
                                block_diag=True)

    for psi_e_1, psi_e_2, psi_b_1, psi_b_2 in izip(psi_exact_1, psi_exact_2,
                                                   psi_block_1, psi_block_2):
        np.testing.assert_allclose(psi_b_1, psi_e_1, atol=1e-7)
        np.testing.assert_allclose(psi_b_2, psi_e_2, atol=1e-7)

    expH.set_iterate(False)

    psi_exact_1 = H.evolve(psi0,
                           0,
                           times,
                           iterate=False,
                           atol=1e-15,
                           rtol=1e-15)
    psi_block_1 = block_op.evolve(psi0,
                                  0,
                                  times,
                                  iterate=False,
                                  atol=1e-15,
                                  rtol=1e-15,
                                  n_jobs=4)

    psi_exact_2 = expH.dot(psi0, time=0.3)
    psi_block_2 = block_op.expm(psi0,
                                H_time_eval=0.3,
                                start=start,
                                stop=stop,
                                iterate=False,
                                num=num,
                                endpoint=True,
                                block_diag=True)

    for psi_e_1, psi_b_1 in izip(psi_exact_1, psi_block_1):
        np.testing.assert_allclose(psi_b_1, psi_e_1, atol=1e-7)

    for psi_e_2, psi_b_2 in izip(psi_exact_2, psi_block_2):
        np.testing.assert_allclose(psi_b_2, psi_e_2, atol=1e-7)

    # imaginary time
    expH = exp_op(H,
                  a=-1,
                  start=start,
                  stop=stop,
                  iterate=True,
                  num=num,
                  endpoint=True)

    times = np.linspace(start, stop, num=num, endpoint=True)

    psi0 = np.random.ranf(H.Ns)
    psi0 /= np.linalg.norm(psi0)

    psi_exact_2 = expH.dot(psi0, time=0.3, shift=-E0)
    psi_block_2 = block_op.expm(psi0,
                                a=-1,
                                shift=-E0,
                                H_time_eval=0.3,
                                start=start,
                                stop=stop,
                                iterate=True,
                                num=num,
                                endpoint=True,
                                block_diag=True)

    for psi_e_2, psi_b_2 in izip(psi_exact_2, psi_block_2):
        np.testing.assert_allclose(psi_b_2, psi_e_2, atol=1e-7)

    # same for iterate=False
    expH.set_iterate(False)

    psi_exact_2 = expH.dot(psi0, time=0.3, shift=-E0)
    psi_block_2 = block_op.expm(psi0,
                                a=-1,
                                shift=-E0,
                                H_time_eval=0.3,
                                start=start,
                                stop=stop,
                                iterate=False,
                                num=num,
                                endpoint=True,
                                block_diag=True)

    for psi_e_2, psi_b_2 in izip(psi_exact_2, psi_block_2):
        np.testing.assert_allclose(psi_b_2, psi_e_2, atol=1e-7)
Esempio n. 13
0
	Expn2 = np.array([Obs2['Ozz_t'],Obs2['Ozz']])
	psi_t2 = Obs2['psi_t']
	Sent2 = Obs2['Sent_time']['Sent']


	np.testing.assert_allclose(Expn,Expn2,atol=atol,rtol=rtol,err_msg='Failed observable comparison!')
	np.testing.assert_allclose(psi_t,psi_t2,atol=atol,rtol=rtol,err_msg='Failed state comparison!')
	np.testing.assert_allclose(Sent,Sent2,atol=atol,err_msg='Failed ent entropy comparison!')

	### check obs_vs_time vs ED

	E,V = H2.eigh()

	psi_t=H2.evolve(psi0,0.0,t,iterate=False,rtol=solver_rtol,atol=solver_atol)
	psi_t4=exp_op(H2,a=-1j,start=0.0,stop=2.0,num=20,endpoint=True,iterate=True).dot(psi0)


	Obs = obs_vs_time(psi_t,t,Obs_list,return_state=True,Sent_args=Sent_args)
	Obs2 = obs_vs_time((psi0,E,V),t,Obs_list,return_state=True,Sent_args=Sent_args)
	Obs4 = obs_vs_time(psi_t4,t,Obs_list,return_state=True,Sent_args=Sent_args)

	psi_t3 = ED_state_vs_time(psi0,E,V,t,iterate=False)
	psi_t33 = np.asarray([psi for psi in ED_state_vs_time(psi0,E,V,t,iterate=True)]).T


	Expn = np.array([Obs['Ozz_t'],Obs['Ozz']])
	psi_t = Obs['psi_t']
	Sent = Obs['Sent_time']['Sent']

	Expn2 = np.array([Obs2['Ozz_t'],Obs2['Ozz']])
Esempio n. 14
0
                               err_msg='mixed: Failed ent entropy comparison!')

    ### check obs_vs_time vs ED

    E, V = H2.eigh()

    psi_t = H2.evolve(psi0,
                      0.0,
                      t,
                      iterate=False,
                      rtol=solver_rtol,
                      atol=solver_atol)
    psi_t4 = exp_op(H2,
                    a=-1j,
                    start=0.0,
                    stop=2.0,
                    num=20,
                    endpoint=True,
                    iterate=True).dot(psi0)

    Obs = obs_vs_time(psi_t,
                      t,
                      Obs_list,
                      return_state=True,
                      Sent_args=Sent_args)
    Obs2 = obs_vs_time((psi0, E, V),
                       t,
                       Obs_list,
                       return_state=True,
                       Sent_args=Sent_args)
    Obs4 = obs_vs_time(psi_t4,
Esempio n. 15
0
Hx_1  = hamiltonian([["+",hx_1],["-",hx_1]],[],basis=basis_1,dtype=np.float64)
#
###### calculate initial states ######
# calculating bandwidth for non-driven hamiltonian
[E_12_min],psi_12 = Hzz_12.eigsh(k=1,which="SA") #
[E_1_min],psi_1 = Hzz_1.eigsh(k=1,which="SA")
# set up the initial states
psi0_12 = psi_12.ravel()
psi0_1 = psi_1.ravel()
#
###### time evolution ######
# stroboscopic time vector
nT = 200 # number of periods to evolve to
t=Floquet_t_vec(Omega,nT,len_T=1) # t.vals=t, t.i=initial time, t.T=drive period
# creating generators of time evolution using exp_op class
U1_12 = exp_op(Hzz_12+A*Hx_12,a=-1j*t.T/4)
U2_12 = exp_op(Hzz_12-A*Hx_12,a=-1j*t.T/2)
U1_1 = exp_op(Hzz_1+A*Hx_1,a=-1j*t.T/4)
U2_1 = exp_op(Hzz_1-A*Hx_1,a=-1j*t.T/2)
# user-defined generator for stroboscopic dynamics 
def evolve_gen(psi0,nT,*U_list):
	yield psi0
	for i in range(nT): # loop over number of periods
		for U in U_list: # loop over unitaries
			psi0 = U.dot(psi0)
		yield psi0
# get generator objects for time-evolved states
psi_12_t = evolve_gen(psi0_12,nT,U2_12,U1_12,U2_12)
psi_1_t = evolve_gen(psi0_1,nT,U2_1,U1_1,U2_1)
#
###### compute expectation values of observables ######
Esempio n. 16
0
x_field = [[g, i] for i in range(L)]
z_field = [[h, i] for i in range(L)]
J_nn = [[J, i, (i + 1) % L] for i in range(L)]  # PBC
# static and dynamic lists
static = [["zz", J_nn], ["z", z_field], ["x", x_field]]
dynamic = []
###### construct Hamiltonian
H = hamiltonian(static, dynamic, dtype=np.float64, basis=basis)
#
###### compute evolution operator as matrix exponential
start, stop, N_t = 0.0, 4.0, 21  # time vector parameters
# define evolution operator
U = exp_op(H,
           a=-1j,
           start=start,
           stop=stop,
           num=N_t,
           endpoint=True,
           iterate=True)
print(U)
#
# compute domain wall initial state
dw_str = "".join("1"
                 for i in range(L // 2)) + "".join("0"
                                                   for i in range(L - L // 2))
i_0 = basis.index(dw_str)  # find index of product state in basis
psi = np.zeros(basis.Ns)  # allocate space for state
psi[i_0] = 1.0  # set MB state to be the given product state
#
##### calculate time-evolved state by successive application of matrix exponential
psi_t = U.dot(
Esempio n. 17
0
 def exponentiate_at_hx(self, hx=0., a=-1j):
     return exp_op(self.hamiltonian_cont(time=hx), a=a)
Esempio n. 18
0
Hzz_2d = hamiltonian([["zz", Jzz_2d]], [],
                     basis=basis_2d,
                     dtype=np.float64,
                     **no_checks)
Hx_2d = hamiltonian([["x", hx_2d]], [],
                    basis=basis_2d,
                    dtype=np.float64,
                    **no_checks)
# calculating bandwidth for non-driven hamiltonian
[E_1d_min], psi_1d = Hzz_1d.eigsh(k=1, which="SA")
[E_2d_min], psi_2d = Hzz_2d.eigsh(k=1, which="SA")
# setting up initial states
psi0_1d = psi_1d.ravel()
psi0_2d = psi_2d.ravel()
# creating generators of time evolution
U1_1d = exp_op(Hzz_1d + omega * Hx_1d, a=-1j * T / 4)
U2_1d = exp_op(Hzz_1d - omega * Hx_1d, a=-1j * T / 2)
U1_2d = exp_op(Hzz_2d + omega * Hx_2d, a=-1j * T / 4)
U2_2d = exp_op(Hzz_2d - omega * Hx_2d, a=-1j * T / 2)
# get generator objects to get time dependent states
psi_1d_t = evolve_gen(psi0_1d, nT, U1_1d, U2_1d, U1_1d)
psi_2d_t = evolve_gen(psi0_2d, nT, U1_2d, U2_2d, U1_2d)
# measure energy as a function of time
Obs_1d_t = obs_vs_time(psi_1d_t, times, dict(E=Hzz_1d), return_state=True)
Obs_2d_t = obs_vs_time(psi_2d_t, times, dict(E=Hzz_2d), return_state=True)
# calculate page entropy density
s_p_1d = np.log(2) - 2.0**(-L_1d // 2 - L_1d) / (2 * (L_1d // 2))
s_p_2d = np.log(2) - 2.0**(-N_2d // 2 - N_2d) / (2 * (N_2d // 2))
# calculating the entanglement entropy density
Sent_time_1d = basis_1d.ent_entropy(
    Obs_1d_t["psi_t"], sub_sys_A=range(L_1d // 2))["Sent_A"] / (L_1d // 2)