def main(): # Parse command line arguements ################################### parser = argparse.ArgumentParser(description=("Search for second order perturbation theory approximable Jij matrices") ) parser.add_argument('lattice_specifier', help=( "Either: L (linear dimensions of the system)" " or the filename base of matrix files") ) parser.add_argument('seed_limit', help = ("Specifying the range of seeds to search through")) parser.add_argument('-o', default='output', help='output filename base') parser.add_argument('-PBC', type = bool, default = True, help = "Specifying PBC") parser.add_argument('-J', type=float, default = 1.0, help = 'Nearest neighbor Ising coupling') parser.add_argument('-max_order', type=int, default = 4, help = 'The maximum Hamming distance between degenerate ground states') args = parser.parse_args() ################################### L = [ int(args.lattice_specifier) ] PBC = args.PBC J = args.J seed_limit = int(args.seed_limit) max_order = int(args.max_order) # Build lattice and basis lattice = tfim.Lattice(L, PBC) N = lattice.N basis = tfim.IsingBasis(lattice) # Specifying parameters needed seed_range = range(seed_limit) # Begin search Jij_array = []; for i in seed_range: Jij = tfim.Jij_instance(N,J,"bimodal",i) Jij_array.append(Jij) # Calculate energy array: indices_array = [] for Jij in Jij_array: Energies = -tfim.JZZ_SK_ME(basis,Jij) GS_energy = np.min(Energies) GS_indices = np.nonzero(Energies == GS_energy)[0] indices_array.append(GS_indices) # Search for Hamming distance 2 seed_list = [] for index, indices in enumerate(indices_array): if tfim_perturbation.judge(max_order, tfim_perturbation.Hamming_array(indices, basis), N): seed_list.append(index) print(seed_list)
def main(): parser = argparse.ArgumentParser() parser.add_argument('-N', type=int, default=16, help='Number of spins') parser.add_argument('-C', type=int, default=3, help='J Matrix configuration') args = parser.parse_args() num_of_spins = args.N configuration = args.C J_Matrix = np.loadtxt("J_Matrices/J" + str(num_of_spins) + "/J_Matrix" + str(configuration) + "/" + str(num_of_spins) + "J_Matrix" + str(configuration) + ".dat") lattice = tfim.Lattice([num_of_spins], True) basis = tfim.IsingBasis(lattice) infdim_Energy_Array = tfim.JZZ_SK_ME(basis, J_Matrix) np.savetxt( "J_Matrices/J" + str(num_of_spins) + "/J_Matrix" + str(configuration) + "/EnergyArray.dat", infdim_Energy_Array)
# In[5]: # Build lattice and basis ################################### lattice = tfim.Lattice(L, PBC) N = lattice.N basis = tfim.IsingBasis(lattice) ################################### # construct random J matrix Jij = tfim.Jij_instance(N, J, "bimodal", Jij_seed) # In[6]: # List out all the spin_states, corresponding indices and energies Energies = -tfim.JZZ_SK_ME(basis, Jij) for index in range(2**N): print(index, basis.state(index), Energies[index]) # In[7]: # Build 2nd order approximated matrix GS_energy, GS_indices = tfim_perturbation.GS(Energies) H_app_0 = tfim_perturbation.H_app_0(GS_energy, GS_indices) H_app_1 = tfim_perturbation.H_app_1(basis, GS_indices, N) H_app_2 = tfim_perturbation.H_app_2(basis, Jij, GS_indices, N, GS_energy)
def tfim_analysis(L, Jij_seed, perturbation_order, h_x_range=np.arange(0, 0.005, 0.0001), PBC=True, J=1): #Initialize the output dictionary containing all the information that we want to know about a specific instance # - isEmpty # - isWorking # both of which contains logical True or False values #Initial set up info = {} # Configure the number of spins to the correct format for analysis L = [L] # Build lattice and basis ################################### lattice = tfim.Lattice(L, PBC) N = lattice.N basis = tfim.IsingBasis(lattice) ################################### # construct random J matrix Jij = tfim.Jij_instance(N, J, "bimodal", Jij_seed) # List out all the spin_states, corresponding indices and energies Energies = -tfim.JZZ_SK_ME(basis, Jij) # for index in range(2 ** N): # print(index, basis.state(index), Energies[index]) GS_energy, GS_indices = tfim_perturbation.GS(Energies) # Specify perturbation order if perturbation_order == 3: analysis_func = tfim_perturbation.app_3_eigensystem_general_matrices H_app_3 = tfim_perturbation.H_app_3(basis, Jij, GS_indices, N, GS_energy) isEmpty = np.allclose(H_app_3, np.zeros((len(GS_indices), len(GS_indices)))) elif perturbation_order == 4: analysis_func = tfim_perturbation.app_4_eigensystem_general_matrices isEmpty = False # Check to see if the max order perturbative term is empty and store this information in "info" info['isEmpty'] = isEmpty # Calculate approximated eigenvalues and eigenstates for range(h_x) app_eigenvalues, app_eigenstates = analysis_func(GS_indices, GS_energy, h_x_range, J, N, basis, Jij) # Calculate exact eigenvalues and eigenstates for range(h_x) exc_eigenvalues, exc_eigenstates = tfim_perturbation.exc_eigensystem( basis, h_x_range, lattice, Energies) # Extract exact ground states exc_GS_eigenstates = np.zeros( (len(h_x_range), len(GS_indices), len(GS_indices))) for i in range(len(h_x_range)): for m, j in enumerate(GS_indices): for n, k in enumerate(GS_indices): exc_GS_eigenstates[i, m, n] = exc_eigenstates[i, j, n] # Extract exact ground energy reordered_app_eigenstates = np.zeros( [len(h_x_range), len(GS_indices), len(GS_indices)]) epsilon = 1 * 10**(-6) for h_x_index in range(len(h_x_range)): if h_x_index < 2: reordered_app_eigenstates[h_x_index] = app_eigenstates[h_x_index] else: for k in range(len(GS_indices) // 2): fidelity_array = [] for v1 in [ reordered_app_eigenstates[h_x_index - 1, :, 2 * k], reordered_app_eigenstates[h_x_index - 1, :, 2 * k + 1] ]: for v2 in [ app_eigenstates[h_x_index, :, 2 * k], app_eigenstates[h_x_index, :, 2 * k + 1] ]: fidelity_array = np.append( fidelity_array, tfim_perturbation.fidelity(v1, v2)) if abs(fidelity_array[0] - max(fidelity_array)) < epsilon: reordered_app_eigenstates[ h_x_index, :, 2 * k] = app_eigenstates[h_x_index, :, 2 * k] reordered_app_eigenstates[h_x_index, :, 2 * k + 1] = app_eigenstates[ h_x_index, :, 2 * k + 1] else: reordered_app_eigenstates[ h_x_index, :, 2 * k] = app_eigenstates[h_x_index, :, 2 * k + 1] reordered_app_eigenstates[h_x_index, :, 2 * k + 1] = app_eigenstates[ h_x_index, :, 2 * k] reordered_exc_GS_eigenstates = np.zeros( [len(h_x_range), len(GS_indices), len(GS_indices)]) epsilon = 1 * 10**(-12) for h_x_index in range(len(h_x_range)): if h_x_index < 2: reordered_exc_GS_eigenstates[h_x_index] = exc_GS_eigenstates[ h_x_index] else: for k in range(len(GS_indices) // 2): fidelity_array = [] for v1 in [ reordered_exc_GS_eigenstates[h_x_index - 1, :, 2 * k], reordered_exc_GS_eigenstates[h_x_index - 1, :, 2 * k + 1] ]: for v2 in [ exc_GS_eigenstates[h_x_index, :, 2 * k], exc_GS_eigenstates[h_x_index, :, 2 * k + 1] ]: fidelity_array = np.append( fidelity_array, tfim_perturbation.fidelity(v1, v2)) if abs(fidelity_array[0] - max(fidelity_array)) < epsilon: reordered_exc_GS_eigenstates[ h_x_index, :, 2 * k] = exc_GS_eigenstates[h_x_index, :, 2 * k] reordered_exc_GS_eigenstates[ h_x_index, :, 2 * k + 1] = exc_GS_eigenstates[h_x_index, :, 2 * k + 1] else: reordered_exc_GS_eigenstates[ h_x_index, :, 2 * k] = exc_GS_eigenstates[h_x_index, :, 2 * k + 1] reordered_exc_GS_eigenstates[ h_x_index, :, 2 * k + 1] = exc_GS_eigenstates[h_x_index, :, 2 * k] # Calculate and plot energy errors corrected_exc_eigenvalues = np.zeros((len(GS_indices), len(h_x_range))) for i in range(len(GS_indices)): for j in range(len(h_x_range)): corrected_exc_eigenvalues[i, j] = exc_eigenvalues[i, j] error_array = np.absolute(corrected_exc_eigenvalues - app_eigenvalues) # Curve fit coeff_matrix = np.zeros((len(GS_indices), 2)) for i in range(len(GS_indices)): pars, cov = curve_fit(f=power_law, xdata=h_x_range, ydata=error_array[i]) coeff_matrix[i] = pars # Check to see if perturbation is working and store it in the info dictionary if info['isEmpty'] == False: judgment, error_classical_GS_index = isWorking(coeff_matrix, perturbation_order) info['isWorking'] = bool(judgment) info['error state index'] = error_classical_GS_index info['error order'] = coeff_matrix[error_classical_GS_index, 1] else: info['isWorking'] = None info['error order'] = None info['error state index'] = None # return info dictionary return info, coeff_matrix[:, 1]
def main(): parser = argparse.ArgumentParser() parser.add_argument('yheight', type=int, help='Height of grid') parser.add_argument('xwidth', type=int, help='Width of grid') parser.add_argument('initial_seed', type=int, help='First Jij seed') parser.add_argument('seed_range', type=int, help='Number of seeds') args = parser.parse_args() PBC = True yheight = args.yheight xwidth = args.xwidth L = [yheight, xwidth] lattice = tfim.Lattice(L, PBC) N = lattice.N basis = tfim.IsingBasis(lattice) initial = args.initial_seed num_seeds = args.seed_range center = (500, 375) ground_states = {} num_missing = 0 different = [] f = open("ground_states.txt", "w+") for seed in range(initial, initial + num_seeds): bonds = bond_list(seed, N, PBC, xwidth, yheight) Jij = make_Jij(N, bonds, lattice) coordList = spinCoords(center, xwidth, yheight) plaq = make_plaquettes(PBC, lattice, N, xwidth, yheight) f_plaq = frustrated(Jij, plaq) node_pairs = plaq_pairing(f_plaq, coordList, PBC, xwidth, yheight) init_ground = initial_ground(node_pairs, xwidth, yheight) p_pairings = init_ground[0] ground_distance = init_ground[1] edges = viable_edges(node_pairs, p_pairings, ground_distance, f_plaq, xwidth, yheight) matchings = plaq_groups(edges, f_plaq, ground_distance) string_groups = add_all_strings(matchings, lattice, coordList) b_bonds = broken_bonds(string_groups, N, coordList, xwidth, yheight) true_ground = make_config(b_bonds, Jij, N, xwidth, lattice, string_groups) ground_config = true_ground[0] true_ground_strings = true_ground[1] number_ground_states = len(true_ground_strings) if number_ground_states == 0: #This means that we assumed a total string length that did not produce any actual ground states. The strategy to fix that is to add to the total string length until we find ground states. found_ground = False inc = True else: found_ground = True #This is the part where it works inc = False #print("Ground distance for something that's working : ", ground_distance) #Below is the piece that isn't working as well. It tends to return some correct ground states, but has not worked fully yet. You can check things with the tfim code, but it takes a while for that to return anything. I wouldn't use tfim for anything too far beyond a 4x4 system, or it takes too long. ''' incremented = 0 while found_ground == False: incremented += 1 ground_distance += 1 #This adds to the total string distance that we are assuming will #produce a ground state if ground_distance > 100: break #Breaks out of the whole thing if the code has run too far edges = viable_edges(node_pairs, p_pairings, ground_distance, f_plaq, xwidth, yheight) if len(edges) != 0: matchings = plaq_groups(edges, f_plaq, ground_distance) string_groups = add_all_strings(matchings, lattice, coordList) b_bonds = broken_bonds(string_groups, N, coordList, xwidth, yheight) true_ground = make_config(b_bonds, Jij, N, xwidth, lattice, string_groups) ground_config = true_ground[0] true_ground_strings = true_ground[1] number_ground_states = len(true_ground_strings) if number_ground_states != 0: #If it finds ground states, we can break out of the while #loop found_ground = True ''' #If you are running with the incremented states, you would change this so that incremented states can also get in (inc stands for incremented and means that we increased the initial minimum assumed string length) if not inc: ground_states.update({seed: ground_config}) ground_config = list(set(ground_config)) ground_config.sort() #This whole piece will check whether you are returning ground states that are correct by checking them against tfim. Again, don't run this bit if you are doing much beyond a 4x4 system or tfim takes forever Jij2 = Jij_convert(Jij, N) #gives the Jij matrix in tfim's form Energies = -1 * tfim.JZZ_SK_ME(basis, Jij2) number_ground = num_ground_states(Energies)[0] states = num_ground_states(Energies)[1] states.sort() mod_states = convert_states(states, basis) mod_states.sort() print("From tfim: ", mod_states) if ground_config != mod_states: different.append(seed) print( "Different!") #Lets you know when this code isn't working print("Different seeds: ", different) f.write(json.dumps(ground_states)) f.close()
def main(): # Parse command line arguments ################################### parser = argparse.ArgumentParser(description=( "Build approximate matrices using first and second order perturbation theory and return its eigenvalues and eigenstates" )) parser.add_argument('lattice_specifier', help=("Linear dimensions of the system")) parser.add_argument('-PBC', type=bool, default=True, help="Specifying PBC") parser.add_argument('-J', type=float, default=1.0, help='Nearest neighbor Ising coupling') parser.add_argument( '-seed', type=int, default=5, help="Specifying the seed for generating random Jij matrices") parser.add_argument('--h_min', type=float, default=0.0, help='Minimum value of the transverse field') parser.add_argument('--h_max', type=float, default=0.1, help='Maximum value of the transverse field') parser.add_argument('--dh', type=float, default=0.01, help='Tranverse fied step size') parser.add_argument('-o', default='output', help='output filename base') parser.add_argument('-d', default='Output_file', help='output directory base') args = parser.parse_args() ################################### # Parameter specification out_filename_base = args.o # Transverse field h_x_range = np.arange(args.h_min, args.h_max + args.dh / 2, args.dh) L = [int(args.lattice_specifier)] PBC = args.PBC J = args.J seed = args.seed # Build lattice and basis lattice = tfim.Lattice(L, PBC) N = lattice.N basis = tfim.IsingBasis(lattice) # Construct random J matrix Jij = tfim.Jij_instance(N, J, "bimodal", seed) ################################### Energies = -tfim.JZZ_SK_ME(basis, Jij) GS_energy, GS_indices = tfim_perturbation.GS(Energies) ################################### H_0 = tfim_perturbation.H_0(GS_energy, GS_indices) H_app_1 = tfim_perturbation.H_app_1(basis, GS_indices, N) H_app_2 = tfim_perturbation.H_app_2(basis, Jij, GS_indices, N, GS_energy) ################################### # Diagonalization loop over h_x_range on H_app app_eigenvalues = np.zeros((len(GS_indices), len(h_x_range))) app_eigenstates = np.zeros( (len(GS_indices), len(GS_indices), len(h_x_range))) for j, h_x in enumerate(h_x_range): H_app = tfim_perturbation.H_app(h_x, H_0, H_app_1, H_app_2, J) app_eigenvalue, app_eigenstate = np.linalg.eigh(H_app) for i in range(len(GS_indices)): app_eigenvalues[i][j] = app_eigenvalue[i] for k in range(len(GS_indices)): app_eigenstates[i][k][j] = app_eigenstate[i][k] ################################### # Make output directory Output = args.d os.mkdir(Output) os.chdir(Output) ################################### # Output Eigenvalue file out_filename_E = out_filename_base + '.dat' # Quantities to write Eigenvalue ouput file phys_keys_E = [] for i in range(len(app_eigenvalues)): eigenvalue_num = 'Eigenvalue ' + str(i + 1) phys_keys_E.append(eigenvalue_num) phys_keys_E.insert(0, 'h_x') phys_E = {} # Dictionary for values # Setup output Eigenvalue data files parameter_string = ("L = {}, PBC = {}, J = {}".format(L, PBC, J)) width = 25 precision = 16 header_list = phys_keys_E header = ''.join( ['{:>{width}}'.format(head, width=width) for head in header_list]) out_eigenvalue_file = open(out_filename_E, 'w') print("\tData will write to {}".format(out_filename_E)) out_eigenvalue_file.write('#\ttfim_diag parameters:\t' + parameter_string + '\n' + '#' + header[1:] + '\n') # Put eigenvalues in phys_E dictionary for i, h_x in enumerate(h_x_range): phys_E['h_x'] = h_x for j, key in enumerate(phys_keys_E[1:]): phys_E[key] = app_eigenvalues[j, i] # Write eigenvalues to output files data_list = [phys_E[key] for key in phys_keys_E] data_line = ''.join([ '{:{width}.{prec}e}'.format(data, width=width, prec=precision) for data in data_list ]) out_eigenvalue_file.write(data_line + '\n') # Close files out_eigenvalue_file.close() ################################### # Output Eigenstate files for file_num in range(len(app_eigenstates)): out_filename_V = out_filename_base + '_' + str(file_num) + '.dat' # Quantities to write Eigenstate output file phys_keys_V = [] for i in range(len(app_eigenstates)): basis = 'Basis ' + str(i + 1) phys_keys_V.append(basis) phys_keys_V.insert(0, 'h_x') phys_V = {} # Dictionary for values # Setup output Eigenstate data files parameter_string = ("L = {}, PBC = {}, J = {}".format(L, PBC, J)) width = 25 precision = 16 header_list = phys_keys_V header = ''.join( ['{:>{width}}'.format(head, width=width) for head in header_list]) out_eigenstate_file = open(out_filename_V, 'w') print("\tData will write to {}".format(out_filename_V)) out_eigenstate_file.write('#\ttfim_diag parameters:\t' + parameter_string + '\n' + '#' + header[1:] + '\n') # Put eigenstates in phys_V dictionary for i, h_x in enumerate(h_x_range): phys_V['h_x'] = h_x for j, key in enumerate(phys_keys_V[1:]): phys_V[key] = app_eigenstates[file_num][j, i] # Write eigenvalues to output files data_list = [phys_V[key] for key in phys_keys_V] data_line = ''.join([ '{:{width}.{prec}e}'.format(data, width=width, prec=precision) for data in data_list ]) out_eigenstate_file.write(data_line + '\n') # Close files out_eigenstate_file.close() ####################################################### # Exit "Output" directory os.chdir("../")