def fsa_ops_from_root(ref, LR): bits = pxp.basis[pxp.keys[ref]] one_loc = [] for m in range(0, np.size(bits, axis=0)): if bits[m] == 1: one_loc = np.append(one_loc, m) if LR == "Left": zero_loc = flippable_zeros[ref][1] elif LR == "Right": zero_loc = flippable_zeros[ref][0] print(bits, one_loc, zero_loc) Hp = np.zeros((pxp.dim, pxp.dim)) for n in range(0, np.size(pxp.basis_refs, axis=0)): state_bits = pxp.basis[n] for m in range(0, np.size(state_bits, axis=0)): if m in one_loc: if state_bits[m] == 1: new_bits = np.copy(state_bits) new_bits[m] = 0 temp_ref = bin_to_int_base_m(new_bits, pxp.base) if temp_ref in pxp.basis_refs: temp_index = pxp.keys[temp_ref] Hp[n, temp_index] = 1 if m in zero_loc: if state_bits[m] == 0: new_bits = np.copy(state_bits) new_bits[m] = 1 temp_ref = bin_to_int_base_m(new_bits, pxp.base) if temp_ref in pxp.basis_refs: temp_index = pxp.keys[temp_ref] Hp[n, temp_index] = 1 Hm = np.conj(np.transpose(Hp)) return Hp, Hm
def group_perm_refs(sector): refs = sector_refs[perm_key(sector)] sector_labels = [] uniq_keys = [] for m in range(0,np.size(refs,axis=0)): goes_to = to_sectors[refs[m]] #goes to key numbers = [] for k in range(0,np.size(goes_to,axis=0)): numbers = np.append(numbers,bin_to_int_base_m(goes_to[k],int(pxp.N/2+1))) number_max = (pxp.N/2+1)*(pxp.N/2)+(pxp.N/2) key = bin_to_int_base_m(numbers,number_max+1) uniq_keys = np.unique(np.append(uniq_keys,key)) uniq_refs = dict() for m in range(0,np.size(uniq_keys,axis=0)): uniq_refs[uniq_keys[m]] = [] for m in range(0,np.size(refs,axis=0)): goes_to = to_sectors[refs[m]] #goes to key numbers = [] for k in range(0,np.size(goes_to,axis=0)): numbers = np.append(numbers,bin_to_int_base_m(goes_to[k],int(pxp.N/2+1))) number_max = (pxp.N/2+1)*(pxp.N/2)+(pxp.N/2) key = bin_to_int_base_m(numbers,number_max+1) uniq_refs[key] = np.append(uniq_refs[key],refs[m]) return uniq_refs
def __init__(self, system, k_refs=None): self.system = system self.k_refs = k_refs #bipartite split computational basis, #to construct coefficient matrices for singular values (entanglement spectrum) self.N_A = int(np.floor(self.system.N / 2)) self.N_B = int(self.system.N - np.floor(self.system.N / 2)) #split basis self.basis_A = self.system.basis[:, :self.N_A] self.basis_B = self.system.basis[:, self.N_A:] self.basis_A_refs = np.zeros(np.size(self.system.basis, axis=0)) self.basis_B_refs = np.zeros(np.size(self.system.basis, axis=0)) for n in range(0, np.size(self.system.basis, axis=0)): self.basis_A_refs[n] = bin_to_int_base_m(self.basis_A[n], self.system.base) self.basis_B_refs[n] = bin_to_int_base_m(self.basis_B[n], self.system.base) self.basis_A_refs_unique = np.unique(self.basis_A_refs) self.basis_B_refs_unique = np.unique(self.basis_B_refs) self.basis_A_keys = dict() self.basis_B_keys = dict() for n in range(0, np.size(self.basis_A_refs_unique, axis=0)): self.basis_A_keys[self.basis_A_refs_unique[n]] = n for n in range(0, np.size(self.basis_B_refs_unique, axis=0)): self.basis_B_keys[self.basis_B_refs_unique[n]] = n
def bipartite_basis_split(basis, base, N): N_A = int(np.floor(N / 2)) N_B = int(N - np.floor(N / 2)) #split basis basis_A = basis[:, :N_A] basis_B = basis[:, N_A:] basis_A_refs = np.zeros(np.size(basis, axis=0)) basis_B_refs = np.zeros(np.size(basis, axis=0)) for n in range(0, np.size(basis, axis=0)): basis_A_refs[n] = bin_to_int_base_m(basis_A[n], base) basis_B_refs[n] = bin_to_int_base_m(basis_B[n], base) return basis_A_refs, basis_B_refs
def energy_basis(state, H): #find sym blocks state has non zero overlap in state_ref = bin_to_int_base_m(state, H.system.base) state_index = find_index_bisection(state_ref, H.system.basis_refs) sym_ref = H.syms.sym_data[state_index, 0] k_refs = H.syms.find_k_ref(sym_ref) #dict to store state in sym sector basis z_sym = dict() eigenvalues = dict() for n in range(0, np.size(k_refs, axis=0)): psi = ref_state(state_ref, H.system) z_sym[n] = psi.sym_basis(k_refs[n], H.syms) eigenvalues[n] = H.sector.eigvalues(k_refs[n]) #dict to store state from sym sector in energy eigenbasis z_energy = dict() for n in range(0, np.size(k_refs, axis=0)): z_energy[n] = np.zeros(np.size(H.sector.eigvalues(k_refs[n])), dtype=complex) #find coefficients by taking overlaps for m in range(0, np.size(z_energy[n], axis=0)): z_energy[n][m] = np.vdot( H.sector.eigvectors(k_refs[n])[:, m], z_sym[n]) #combine all sym sectors z_init = z_energy[0] eig_f = eigenvalues[0] for n in range(1, len(z_energy)): z_init = np.append(z_init, z_energy[n]) eig_f = np.append(eig_f, eigenvalues[n]) return z_init, eig_f
def __init__(self,order,pol,system,shift=0): self.system = system self.order = order #sets the bit representation |1,0...> zm=np.zeros(self.system.N) zm[0] = pol count=1 for n in range(1,np.size(zm,axis=0)): if count<order: zm[n] = 0 count = count + 1 else: zm[n] = pol count = 1 #count zeros at end to check state is act z_n no_zeros=0 for n in range(np.size(zm,axis=0)-1,-1,-1): if zm[n] == pol: break no_zeros = no_zeros + 1 if no_zeros == order-1: self.bits = zm else: print("ERROR Z_"+str(order)+" not at this chain length.") for n in range(0,shift): self.bits = cycle_bits_state(self.bits) self.ref = bin_to_int_base_m(self.bits,self.system.base) self.key = system.keys[self.ref]
def sym_op(self,number,m): if m % 2 == 0: return int(number) else: state = self.system.basis[self.system.keys[number]] new_state = (-1)*(state-1/2*np.ones(np.size(state)))+1/2 new_ref = bin_to_int_base_m(new_state,self.system.base) return new_ref
def create_orbit(self,state): state_bin = self.system.basis[self.system.keys[state]] new_state = (-1)*(state_bin-1/2*np.ones(np.size(state_bin)))+1/2 new_ref = bin_to_int_base_m(new_state,self.system.base) if new_ref == state: return np.array((state)) else: return np.array((state,new_ref))
def gen_basis(self): self.basis = self.gen_P0K_basis() self.basis_refs = np.zeros(np.size(self.basis, axis=0)) self.keys = dict() for n in range(0, np.size(self.basis, axis=0)): self.basis_refs[n] = bin_to_int_base_m(self.basis[n], self.base) self.keys[self.basis_refs[n]] = n self.dim = np.size(self.basis_refs)
def sym_op(self,number,m): if m % 2 == 0: return int(number) else: state = self.system.basis[self.system.keys[number]] parity_state = np.flip(state,0) parity_ref = bin_to_int_base_m(parity_state,self.system.base) return parity_ref
def create_orbit(self,state): state_bin = self.system.basis[self.system.keys[state]] state_pair = np.flip(state_bin,0) pair_ref = bin_to_int_base_m(state_pair,self.system.base) if pair_ref == state: return np.array((state)) else: return np.array((state,pair_ref))
def m_pair_hash(m_pair,s1,s2): base = int(np.max(np.array((4*s1,4*s2)))) temp = np.copy(m_pair) temp[0] = temp[0] + s1 temp[1] = temp[1] + s2 temp = 2*temp key = bin_to_int_base_m(temp,base) return key
def fsa_ops_root_to_target(root_ref, target_ref): root_bits = pxp.basis[pxp.keys[root_ref]] target_bits = pxp.basis[pxp.keys[target_ref]] sm_loc = [] sp_loc = [] for n in range(0, np.size(root_bits, axis=0)): if root_bits[n] == 1 and target_bits[n] == 0: sm_loc = np.append(sm_loc, n) if root_bits[n] == 0 and target_bits[n] == 1: sp_loc = np.append(sp_loc, n) #construct FSA op Hp = np.zeros((pxp.dim, pxp.dim)) for n in range(0, np.size(pxp.basis_refs, axis=0)): state_bits = pxp.basis[n] for m in range(0, np.size(state_bits, axis=0)): if m == np.size(state_bits) - 1: mp1 = 0 else: mp1 = m + 1 if m == 0: mm1 = np.size(state_bits) - 1 else: mm1 = m - 1 if m in sm_loc: if state_bits[mm1] == 0 and state_bits[m] == 1 and state_bits[ mp1] == 0: new_bits = np.copy(state_bits) new_bits[m] = 0 new_ref = bin_to_int_base_m(new_bits, pxp.base) if new_ref in pxp.basis_refs: new_index = pxp.keys[new_ref] Hp[n, new_index] = 1 if m in sp_loc: if state_bits[mm1] == 0 and state_bits[m] == 0 and state_bits[ mp1] == 0: new_bits = np.copy(state_bits) new_bits[m] = 1 new_ref = bin_to_int_base_m(new_bits, pxp.base) if new_ref in pxp.basis_refs: new_index = pxp.keys[new_ref] Hp[n, new_index] = 1 Hm = np.conj(np.transpose(Hp)) return Hp, Hm
def sym_op(self,number,m): state = self.system.basis[self.system.keys[number]] d = np.size(state) state1 = state[:int(d/2)] state2 = state[int(d/2):] state1_new = np.flip(state1) state2_new = state2 state = np.append(state1_new,state2_new) return bin_to_int_base_m(state,self.system.base)
def sym_op(self,number,m): state = self.system.basis[self.system.keys[number]] L=np.size(state) for k in range(0,m): trans_state=np.zeros(np.size(state)) trans_state[0:L-1] = state[1:L] trans_state[L-1] = state[0] state = trans_state state = np.flip(state) return bin_to_int_base_m(state,self.system.base)
def find_eig(self, index=None, k0=None, verbose=False): if index is None: self.table["no_sym"].e, self.table["no_sym"].u = np.linalg.eigh( self.table["no_sym"].H) else: key = bin_to_int_base_m(index, self.system.N) self.table[key].e, self.table[key].u = np.linalg.eigh( self.table[key].H) if verbose is True: print("Found Eigenvalues")
def bulk_eval(state, H, k_vec=None): if k_vec is None: #no symmetry, use full basis z_ref = bin_to_int_base_m(state, H.system.base) z_index = find_index_bisection(z_ref, H.system.basis_refs) z_energy = H.sector.eigvectors()[z_index, :] eigenvalues = H.sector.eigvalues() else: #symmetry used, just plot the given sym_block z_ref = bin_to_int_base_m(state, H.system.base) psi = ref_state(z_ref, H.system) z_mom = psi.sym_basis(k_vec, H.syms) # z_mom = z_mom * np.power(np.vdot(z_mom,z_mom),-0.5) z_energy = np.zeros(np.size(H.sector.eigvalues(k_vec)), dtype=complex) for n in range(0, np.size(z_energy, axis=0)): z_energy[n] = np.vdot(z_mom, H.sector.eigvectors(k_vec)[:, n]) eigenvalues = H.sector.eigvalues(k_vec) overlap = np.log10(np.abs(z_energy)**2) return overlap
def create_orbit(self,state_ref): if state_ref == 0: return np.array((state_ref)) else: conjugated_state = np.copy(self.system.basis[self.system.keys[state_ref]]) for m in range(0,np.size(conjugated_state,axis=0)): if conjugated_state[m] != 0: conjugated_state[m] = (self.system.base-conjugated_state[m]) % self.system.base conjugated_ref = bin_to_int_base_m(conjugated_state,self.system.base) return np.array((state_ref,conjugated_ref))
def sym_op(self,state_ref,m): if m % 2 == 0: return int(state_ref) else: conjugated_state = np.copy(self.system.basis[self.system.keys[state_ref]]) for m in range(0,np.size(conjugated_state,axis=0)): if conjugated_state[m] != 0: conjugated_state[m] = (self.system.base-conjugated_state[m]) % self.system.base conjugated_ref = bin_to_int_base_m(conjugated_state,self.system.base) return conjugated_ref
def find_subcube_basis(root_ref, bits_to_add, LR): root_bits = pxp.basis[pxp.keys[root_ref]] one_loc = [] for m in range(0, np.size(root_bits, axis=0)): if np.abs(root_bits[m]) > 1e-5: one_loc = np.append(one_loc, m) poss_zero_loc = [] for m in range(0, np.size(root_bits, axis=0)): if m == 0: mm1 = pxp.N - 1 else: mm1 = m - 1 if m == pxp.N - 1: mp1 = 0 else: mp1 = m + 1 if LR == "Right": if m % 2 != 0: if root_bits[mm1] == 0 and root_bits[mp1] == 0 and root_bits[ m] == 0: poss_zero_loc = np.append(poss_zero_loc, m) if LR == "Left": if m % 2 == 0: if root_bits[mm1] == 0 and root_bits[mp1] == 0 and root_bits[ m] == 0: poss_zero_loc = np.append(poss_zero_loc, m) bit_loc = np.append(one_loc, poss_zero_loc) dim = np.sum(from_sector[root_ref]) + bits_to_add subcube_system = unlocking_System([0, 1], "open", 2, dim) subcube_system.gen_basis() init_bits = np.append(np.ones(np.size(one_loc)), np.zeros(np.size(poss_zero_loc))) subcube_hamming = find_hamming_sectors(init_bits, subcube_system) basis = np.zeros((pxp.dim, len(subcube_hamming))) if np.size(poss_zero_loc) == bits_to_add: for m in range(0, len(subcube_hamming)): temp_state = np.zeros(pxp.dim) refs = subcube_hamming[m] for u in range(0, np.size(refs, axis=0)): sub_bits = subcube_system.basis[subcube_system.keys[refs[u]]] temp_bits = np.zeros(pxp.N) for k in range(0, np.size(sub_bits, axis=0)): temp_bits[int(bit_loc[k])] = sub_bits[k] temp_ref = bin_to_int_base_m(temp_bits, pxp.base) temp_state[pxp.keys[temp_ref]] = 1 temp_state = temp_state / np.power(np.vdot(temp_state, temp_state), 0.5) basis[:, m] = temp_state return basis else: return basis
def update_H_entry(self, i, j, val, k_vec=None, dim=None): if k_vec is None: #init hamiltonian matrix as emtpy if "no_sym" not in list(self.table.keys()): self.table["no_sym"] = H_entry( np.zeros((dim, dim), dtype=complex)) self.table["no_sym"].H[i, j] = self.table["no_sym"].H[i, j] + val else: key = bin_to_int_base_m(k_vec, self.system.N) #hash function if key not in list(self.table.keys()): self.table[key] = H_entry(np.zeros((dim, dim), dtype=complex)) self.table[key].H[i, j] = self.table[key].H[i, j] + val
def __init__(self, name, bc, N): self.base = 3 #3level system self.name = name self.bc = bc self.N = N self.basis = self.gen_basis() self.basis_refs = np.zeros(np.size(self.basis, axis=0), dtype=int) self.keys = dict() for n in range(0, np.size(self.basis, axis=0)): self.basis_refs[n] = bin_to_int_base_m(self.basis[n], self.base) self.keys[self.basis_refs[n]] = n
def perm_matrix(N, perm): P = np.zeros((pxp.dim, pxp.dim)) for n in range(0, np.size(pxp.basis, axis=0)): bits = np.copy(pxp.basis[n]) new_bits = np.copy(pxp.basis[n]) for m in range(0, np.size(perm, axis=0)): loc = int(2 * m) new_bits[loc] = bits[2 * perm[m]] new_bits[loc + 1] = bits[2 * perm[m] + 1] new_ref = bin_to_int_base_m(new_bits, pxp.base) if new_ref in pxp.basis_refs: new_index = pxp.keys[new_ref] P[new_index, n] += 1 return P
def create_orbit(self,state): state_bin = self.system.basis[self.system.keys[state]] state_pair = np.flip(state_bin,0) new_state = np.copy(state_pair) for m in range(0,np.size(state_pair,axis=0)): if state_pair[m] == 0: new_state[m] = 2 elif state_pair[m] == 2: new_state[m] = 0 pair_ref = bin_to_int_base_m(new_state,self.system.base) if pair_ref == state: return np.array((state)) else: return np.array((state,pair_ref))
def bulk_eval(state, t, H, use_syms=None): if use_syms == None: z_ref = bin_to_int_base_m(state, H.system.base) z_index = find_index_bisection(z_ref, H.system.basis_refs) z_init = H.sector.eigvectors()[z_index, :] eig_f = H.sector.eigvalues() else: z_init, eig_f = energy_basis(state, H) fidelity_y = np.zeros(np.size(t)) for n in range(0, np.size(t, axis=0)): evolved_state = time_evolve_state(z_init, eig_f, t[n]) fidelity_y[n] = np.abs(np.vdot(evolved_state, z_init))**2 return fidelity_y
def eval(state, t, H, use_syms=None): if use_syms == None: z_ref = bin_to_int_base_m(state, H.system.base) z_index = find_index_bisection(z_ref, H.system.basis_refs) z_init = H.sector.eigvectors()[z_index, :] eig_f = H.sector.eigvalues() else: z_init, eig_f = energy_basis(state, H) evolved_state = time_evolve_state(z_init, eig_f, t) print(np.abs(np.vdot(z_init, evolved_state))**2) # if t<0.5: # return -100 # else: return np.abs(np.vdot(z_init, evolved_state))**2
def sym_op(self,number,m): if m % 2 == 0: return int(number) else: state = self.system.basis[self.system.keys[number]] parity_state = np.flip(state,0) new_state = np.copy(parity_state) #now invert for m in range(0,np.size(parity_state,axis=0)): if parity_state[m] == 0: new_state[m] = 2 elif parity_state[m] == 2: new_state[m] = 0 parity_ref = bin_to_int_base_m(new_state,self.system.base) return parity_ref
def U1_sector(self, n_up): from sympy.utilities.iterables import multiset_permutations root = np.append(np.ones(n_up), np.zeros(self.N - n_up)).astype(int) basis = np.array(list(multiset_permutations(root))) new_basis = deepcopy(self) new_basis.basis = basis new_basis.basis_refs = np.zeros(np.size(new_basis.basis, axis=0)) new_basis.keys = dict() for n in range(0, np.size(new_basis.basis_refs)): new_basis.basis_refs[n] = bin_to_int_base_m( new_basis.basis[n], new_basis.base) new_basis.keys[new_basis.basis_refs[n]] = n new_basis.dim = np.size(new_basis.basis_refs) return new_basis
def Hm_from_ref(ref): bits = pxp.basis[pxp.keys[ref]] one_loc = [] for m in range(0, np.size(bits, axis=0)): if bits[m] == 1: one_loc = np.append(one_loc, m) Hm = np.zeros((pxp.dim, pxp.dim)) for n in range(0, np.size(pxp.basis_refs, axis=0)): state_bits = pxp.basis[n] for m in range(0, np.size(one_loc, axis=0)): if state_bits[int(one_loc[m])] == 1: new_bits = np.copy(state_bits) new_bits[int(one_loc[m])] = 0 temp_ref = bin_to_int_base_m(new_bits, pxp.base) Hm[n, pxp.keys[temp_ref]] = 1 return Hm
def join_basis_states(n, m, system, double_system): even_state_bits = system.basis[n] odd_state_bits = system.basis[m] full_bits = np.zeros(2 * np.size(even_state_bits)) c_even = 0 c_odd = 0 for n in range(0, np.size(full_bits, axis=0)): if n % 2 == 0: full_bits[n] = even_state_bits[c_even] c_even = c_even + 1 else: full_bits[n] = odd_state_bits[c_odd] c_odd = c_odd + 1 full_bits_ref = bin_to_int_base_m(full_bits, double_system.base) if full_bits_ref in double_system.basis_refs: return full_bits_ref else: return None