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)
Exemple #2
0
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)
Exemple #3
0
# 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)
Exemple #4
0
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]
Exemple #5
0
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()
Exemple #6
0
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("../")