def apply_H_cin(self, i):
     """
     @param i : unsigned integer, state in occupation representation.
     """
     targets = []
     # for each site
     for site in range(1, self.nb_sites + 1):
         # Perform the following tasks for both spins
         for spin in [site, site + self.nb_sites]:
             # if there is a current spin at site
             if (gmpy2.bit_test(i, spin - 1)):
                 # loop over each neighbors
                 for neighbor in self.get_neighbors(site):
                     # add element to the answer if site is vacant
                     if (not gmpy2.bit_test(
                             i, int(spin - site + neighbor - 1))):
                         # count the number of electrons between the creation and annihilation sites
                         create_at = int(spin - site + neighbor - 1)
                         destroy_at = int(spin - 1)
                         n_el = 0
                         for c in np.arange(
                                 min(create_at, destroy_at) + 1,
                                 max(create_at, destroy_at)):
                             if gmpy2.bit_test(i, int(c)):
                                 n_el += 1
                         targets.append([
                             ((-1)**(1 + n_el)) * self.t,
                             gmpy2.bit_flip(gmpy2.bit_flip(i, spin - 1),
                                            int(spin - site + neighbor - 1))
                         ])
     return targets
Пример #2
0
    def get_rho_from_v(self,v,l):
        '''
        :param v: wave vector
        :param l: number of sites
        :return: <psi|cidci|psi>
        '''
        # initialize the density matrix
        rho = np.zeros([4*l,4*l],dtype=complex)

        # populate the matrix

        # iterate over all impurity+bath positions i
        for i in np.arange(4*l,dtype=int):
            # iterate over all impurity+bath positions j
            for j in np.arange(4*l,dtype=int):
                #iterate over all elements in the basis of the look-up table
                for run_k,k in enumerate(self.J):
                    #check if a+i aj|k> is not null
                    if(gmpy2.bit_test(int(k),int(j))):
                        if(gmpy2.bit_test(int(k),int(i))==0 or i==j):
                            new_state=gmpy2.bit_flip(int(k),int(j))
                            new_state=gmpy2.bit_flip(new_state,int(i))
                            run_new = self.state2index(new_state)
                            #and don't forget the sign !
                            occupancy_between=0
                            for l in np.arange(min(i,j)+1,max(i,j)):
                                occupancy_between+=gmpy2.bit_test(int(k),int(l))
                            rho[i,j]+=(-1)**occupancy_between*np.conjugate(v[run_new])*v[run_k]
        return rho
Пример #3
0
    def get_rho_impurity(self, impurity_index, verbose=False):
        '''
        :param impurity_index: index of the impurity
        :return: single particle density matrix in the impurity basis
        '''
        # Get ground state (updates the chemical potential)
        vs = self.get_ground_state(impurity_index, verbose)
        v = np.zeros(np.shape(vs[0]), dtype=complex)
        if verbose:
            print(np.around(vs, 2))
        # initialize the density matrix
        rho = np.zeros([4 * len(impurity_index), 4 * len(impurity_index)],
                       dtype=complex)

        # the coefs part ensures that the ground state has a defined spin on the impurity if it is degenerated
        coefs = np.zeros(len(vs), dtype=complex)
        for k, psi in enumerate(vs):
            for i in np.arange(len(psi)):
                impurity_down = 0
                for j in np.arange(len(impurity_index)):
                    if (gmpy2.bit_test(int(i), int(j + len(impurity_index)))
                            and not gmpy2.bit_test(int(i), int(j))):
                        impurity_down += 1
                coefs[k] += impurity_down * psi[i]
        if len(coefs) == 2:
            if (np.abs(coefs[0]) > 0.0001):
                c = coefs[1] / coefs[0]
                beta = 1 / np.sqrt(1 + c**2)
                alpha = -beta * c
                v = alpha * vs[0] + beta * vs[1]
            else:
                v = vs[0]
        else:
            v = vs[0]
        v = v / np.linalg.norm(v)
        if verbose:
            print("new ground state")
            print(v)
        # populate the matrix
        # iterate over all impurity+bath positions i
        for i in np.arange(4 * len(impurity_index), dtype=int):
            # iterate over all impurity+bath positions j
            for j in np.arange(4 * len(impurity_index), dtype=int):
                #iterate over all elements in the basis of the Fock space
                for k in np.arange(2**(4 * len(impurity_index)), dtype=int):
                    #check if a+i aj|k> is not null
                    if (gmpy2.bit_test(int(k), int(j))):
                        if (gmpy2.bit_test(int(k), int(i)) == 0 or i == j):
                            new_state = gmpy2.bit_flip(int(k), int(j))
                            new_state = gmpy2.bit_flip(new_state, int(i))
                            #and don't forget the sign !
                            occupancy_between = 0
                            for l in np.arange(min(i, j) + 1, max(i, j)):
                                occupancy_between += gmpy2.bit_test(
                                    int(k), int(l))
                            rho[i,
                                j] += (-1)**occupancy_between * np.conjugate(
                                    v[new_state]) * v[k]
        return rho
Пример #4
0
    def h_2_cdef(self,state_i,state_j):
        '''
        :param state_j: (int) state where the destruction happened
        :param state_i: (int) state where the creation happened
        :return: The "2 particles" energy for 2 jump from site d towards site c
        '''
        jumps = state_i^state_j
        # get the position of the 2 destruction and creation sites
        d_sites = int(state_j & jumps)
        c_sites = int((state_i & jumps))
        found_c1 = False
        found_d1 = False
        c1=0
        c2=0
        d1=0
        d2=0
        for i in np.arange(self.imp_bath_size):
            i=int(i)
            if(gmpy2.bit_test(d_sites,i)):
                if found_d1:
                    d2=i
                else:
                    found_d1=True
                    d1=i
            elif(gmpy2.bit_test(c_sites,i)):
                if found_c1:
                    c2=i
                else:
                    found_c1=True
                    c1=i

        # compute the term
        h=self.get_U_tilda(c1,d1,c2,d2)-self.get_U_tilda(c1,d2,c2,d1)-self.get_U_tilda(c2,d1,c1,d2)+self.get_U_tilda(c2,d2,c1,d1)

        # get the occupation between c2 d2
        occupied = 0
        for k in np.arange((min(c2, d2) + 1), max(c2, d2)):
            occupied += gmpy2.bit_test(state_j, int(k))

        s1 = (-1) ** (occupied)

        # compute the intermediary state
        tmp_state = gmpy2.bit_flip(state_j,c2)
        tmp_state = gmpy2.bit_flip(tmp_state,d2)
        # get the occupation berween c1 d1
        occupied = 0
        for k in np.arange((min(c1, d1) + 1), max(c1, d1)):
            occupied += gmpy2.bit_test(tmp_state, int(k))

        s2 = (-1) ** (occupied)

        return s1*s2*h
    def get_random_adjacent_state(self, i):
        '''
        :param i: (integer) state which is in the binary representation state
        :return: state j which is obtained by permuting one electron and one hole from state i
        '''
        pos_e = random.randint(
            1, self.nb_electrons)  # we will move the pos_e.th. electron
        pos_h = random.randint(
            1, self.nb_sites * self.nb_flavors - self.nb_electrons
        )  # we will permute the electron with the pos_h th. hole

        count_e = 0
        count_h = 0  #count the number of visited bit with electrons and holes

        has_flipped = False  # if we have already made a move

        for site in range(0, self.nb_flavors *
                          self.nb_sites):  #we loop over each bit of i.
            #update the number of visited bits with electrons and holes
            if (gmpy2.bit_test(i, site)):
                count_e += 1
            else:
                count_h += 1
            #Flip the bit if it's the correct position
            if (count_e == pos_e):
                i = gmpy2.bit_flip(i, site)
                count_e += 1  #update count_e to not enter the condition on the next loop
                if not has_flipped:  #if it's the first flip
                    has_flipped = True
                else:  #if we already made a move, then we can exist the loop
                    break
            elif (count_h == pos_h):
                i = gmpy2.bit_flip(i, site)
                count_h += 1
                if not has_flipped:  #if it's the first flip
                    has_flipped = True
                else:  #if we already made a move, then we can exist the loop
                    break
        return i
 def apply_c(self, a, i, dagger=False):
     '''
     compute C(?dagger)(a)|i>
     :param i: (int) binary representation of state i in occupation state
     :param a: (int) number of the site(+spin) on which we want to apply cdagger
     :param dagger: (bool) if True, return cdagger|i>, othervise c|i>
     :return: (int,int) 1 or -1, binary representation of state cd|i> in occupation state
     '''
     #Get the ath state
     ath_state = gmpy2.bit_test(i, a)
     #if the site is empty and we want to destroy of occupied and we want to create
     if (ath_state == dagger):
         return [0, 0]
     # Othervise
     else:
         # count the number of occupied states before a to get the phase
         nb_bits_on_before_a = gmpy2.popcount(i % (1 << a))
         # flip the ath bit
         new_state = gmpy2.bit_flip(i, a)
         # return the phase and the new state
         return [(-1)**nb_bits_on_before_a, new_state]
Пример #7
0
    def apply_c_dagger(self,state,a):
        '''
        Compute c_a+|state>
        :param state: integer representation of quantum state
        :param a: spin-site where we will apply c
        :return: sign (+-1) and new state
        '''
        # Make sure that state and the site are casted correctly
        state = int(state)
        a = int(a)
        # check the occupation until a
        sgn = (-1)**self.occupation_between(state,-1,a) # -1 because we count the first state at 0

        # check that there is an electron at a
        if gmpy2.bit_test(state, a):
            # if there is already an electron, set the sgn to 0 (and state to 0 as a convention)
            sgn=0
            state=0
        else :
            # otherwise we flip the bit
            state = gmpy2.bit_flip(state,a)

        return sgn,state