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
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
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
def apply_H_pot(self, i): """ @param i : unsigned integer, state in occupation representation. """ potential_energy = 0 ## loop over the sites for site in range(0, self.nb_sites): if (gmpy2.bit_test(i, site) and gmpy2.bit_test(i, site + self.nb_sites)): potential_energy += self.U return [[potential_energy, i]]
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 generateKeyPairsBulk(pvk_list): count = len(pvk_list) table = [] # generate a table of points G, 2G, 4G, 8G...(2^255)G table.append(G) for i in range(1, 256): table.append(Point_Doubling(table[i - 1])) pub_list = [Point.IDENTITY_ELEMENT for i in range(count)] for i in range(256): runList = [] # // calculate (Px - Qx) for j in range(count): k = pvk_list[j] if gmpy2.bit_test(k, i): if pub_list[j] == Point.IDENTITY_ELEMENT: run = 2 else: run = (pub_list[j].x - table[i].x) % modulo else: run = 2 runList.append(run) # // calculate 1/(Px - Qx) runList = bulkInversionModP(runList) # // complete the addition for j in range(count): k = pvk_list[j] if gmpy2.bit_test(k, i): if pub_list[j] == Point.IDENTITY_ELEMENT: pub_list[j] = table[i] else: rise = (pub_list[j].y - table[i].y) % modulo # // s = (Py - Qy)/(Px - Qx) s = rise * runList[j] # //rx = (s*s - px - qx) % _p; rx = (s * s - pub_list[j].x - table[i].x) % modulo # //ry = (s * (px - rx) - py) % _p; ry = ((s * (pub_list[j].x - rx)) % modulo - pub_list[j].y) % modulo pub_list[j] = Point(rx, ry) return pub_list
def check_top_row(mask: Bitmap, col: PlayerAction, board_shp: Tuple) -> bool: """ Checks whether the top row of the given column is full :param mask: bitmap representing positions of both players :param col: the column to be checked :param board_shp: the shape of the game board :return: True if the top row is full, False if it is empty """ bit_pos = col * board_shp[1] + board_shp[0] - 1 return bit_test(mask, bit_pos)
def h_2_cd(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 a jump from site d towards site c ''' jump = state_i^state_j d = int(math.log2(state_j & jump)) c = int(math.log2(state_i & jump)) h=0 state_i=int(state_i) state_j=int(state_j) for k in np.arange(self.imp_bath_size): k=int(k) occ_k_1=gmpy2.bit_test(state_i,k) occ_k_2=gmpy2.bit_test(state_j,k) occ_k_3=gmpy2.bit_test(state_i,k)*(k!=c) occ_k_4=gmpy2.bit_test(state_j,k)*(k!=d) if(occ_k_1==1): h+=self.get_U_tilda(k,k,c,d) if(k!=c and k!=d and occ_k_1==1): h+=-self.get_U_tilda(k,d,c,k)+self.get_U_tilda(c,k,k,d) h-=self.get_U_tilda(c,k,k,d) if(occ_k_2==1): h+=self.get_U_tilda(c,d,k,k) #if(occ_k_2==1): # h+=self.get_U_tilda(c,d,k,k) #if(occ_k_3==1): # h-=self.get_U_tilda(k,d,k,c) #if(occ_k_4==1): # h-=self.get_U_tilda(c,k,d,k) #h+=self.get_U_tilda(c,k,d,k) #Check for the sign coming from c+i cj occupied = 0 for k in np.arange((min(c, d) + 1), max(c, d)): occupied += gmpy2.bit_test(state_j, int(k)) sign = (-1) ** (occupied) return sign*h
def h_2_ii(self,state,verbose=False): ''' :param state: (int) binary occupation number :return: The "on site" energy (site correspond to impurity or bath) of state i ''' h=0 state=int(state) if verbose: print("considering state "+str(state)) for m in np.arange(self.imp_bath_size): for n in np.arange(self.imp_bath_size): m = int(m) n = int(n) occ_m = gmpy2.bit_test(state, m) occ_n = gmpy2.bit_test(state, n) if m!=n: #direct term h+=self.get_U_tilda(m,m,n,n)*occ_n*occ_m # cross term h+=self.get_U_tilda(m,n,n,m)*occ_m*(1-occ_n) else: h+=self.get_U_tilda(m,m,m,m)*occ_m return h
def valid_actions(mask: Bitmap, board_shp: Tuple) -> list: """ Determines which actions are valid for the current game state :param mask: bitmap representing positions of both players :param board_shp: the shape of the game board :return: array of valid actions """ # actions = np.ndarray(0) actions = [] for col in range(board_shp[1]): bit_pos = col * board_shp[1] + board_shp[0] - 1 if not bit_test(mask, bit_pos): # actions = np.append(actions, col) actions.append(col) return actions
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]
def occupation_between(self,state,a,b): ''' Return the number of occupied sites between a and b :param state: integer representation of a quantum state :param a: "min" site :param b: "max" site :return: number of occupied states between min and max ''' # cast the state state = int(state) # make sure that a is the min and b the max a,b=np.sort([a,b]) nb_el=0 # numer of electrons between the two sites # loop over all sites between a and b for runner in np.arange(a+1,b,dtype="int"): runner = int(runner) # add an electron if present at site runner nb_el+=gmpy2.bit_test(state,runner) return nb_el
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_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
def int2representation(self, i): representation = np.zeros([self.nb_sites * self.nb_flavors]) for r in np.arange(0, np.size(representation)): if (gmpy2.bit_test(int(i), int(r))): representation[r] = 1 return representation
def H_ij(self,i,j,verbose=False): ''' Compute <i|H|j> :param i: int, binary representation of state |i> :param j: int, binary representation of state |j> :return: <i|H|j> ''' i+=gmpy2.mpz(0) j+=gmpy2.mpz(0) L=int(len(self.impurity_index)*2) # L is the total number of site (bath + impurity) impurity_site=[x-1 for x in self.impurity_index] bath_site=[] #build the bath site for n in np.arange(L): if n not in impurity_site: bath_site.append(int(n)) # if there is a different number of electron, return 0 if(gmpy2.popcount(i)!=gmpy2.popcount(j)): if verbose: print("Not the same number of electron") return 0 # otherwise prepare to sum hij=0 # H(2) contribution, we need to distinguish between 3 cases, i.e. 0 jump, 1 jump and 2 jumps # jump has bit on on the sites that differs jump = i ^ j # first case 0 differences if(gmpy2.popcount(jump)==0): if(verbose): print("0 dif contr "+str(self.h_2_ii(i))) hij += self.h_2_ii(i) hij -= self.mu*gmpy2.popcount(i) #second case 2 differences (one jump) elif(gmpy2.popcount(jump)==2): if(verbose): print("2 dif contr "+str(self.h_2_cd(state_i=i,state_j=j))) hij+= self.h_2_cd(state_i=i,state_j=j) # last possibility : 2 jumps elif(gmpy2.popcount(jump)==4): if(verbose): print("4 dif contr "+str(self.h_2_cdef(i,j))) hij+=self.h_2_cdef(i,j) # H(1) contribution if (gmpy2.popcount((i^j))==2): if verbose: print("One jump") # jump has bit on on the 2 sites that differs jump=i^j # we now look for the index of the sites that were destroyed and created destruction_site = int(math.log2(j&jump) ) creation_site = int(math.log2(i&jump)) if verbose: print("Site of interest : cration at "+str(creation_site)+" and destruction at "+str(destruction_site)) occupied=0 for k in np.arange((min(creation_site,destruction_site)+1),max(creation_site,destruction_site)): occupied+=gmpy2.bit_test(j,int(k)) sign = (-1)**(occupied) # we finally look at the element t = self.T_tilda[creation_site,destruction_site] if verbose: print("t between "+str(creation_site)+" and "+str(destruction_site)+" = "+str(t)) print("occupation = "+str(occupied)) hij+= sign*(t) # Kinetic diagonal elements may have appeared during the transformation elif i==j: for runner in np.arange(2*self.imp_bath_size): if(gmpy2.bit_test(int(i),int(runner))): hij+=self.T_tilda[runner,runner] return hij