def FindMinimumInversePower(foldname): """ Finds the true minimum corresponding: Note Gradient Descent step should be adequately small for this to work """ foldpath = BASE_DIRECTORY + "/" + foldname sysparams = load_params(foldpath) (hs_radii, initial_coords, box_length) = load_secondary_params(foldpath) box_length = float(box_length) boxv = [box_length] * sysparams.ndim.value potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=hs_radii * 1.0, boxvec=boxv, ) print(box_length, "box_length") print(len(initial_coords)) # initial_coords = np.loadtxt(foldpath + '/coords_of_minimum.txt', # delimiter=',') print(initial_coords, "initial_coords") # ret = steepest_descent(initial_coords, potential, dx=1e-4) # ret = modifiedfire_cpp(initial_coords, potential, iprint=1, tol=1e-4) # E, V = print(potential.getEnergyGradient(initial_coords)) # ret = quench_mixed_optimizer(potential, initial_coords, conv_tol=1e-100) # ret = quench_mixed_optimizer(potential, initial_coords, conv_tol=1e-100, nsteps=3000) # ret = quench_steepest( # potential, # initial_coords, # make sure right coords are being passed # stepsize=0.0001, # nsteps=1000, # tol=1e-7) # ret = quench_cvode_opt(initial_coords, potential, ) ret = quench_cvode_opt(initial_coords, potential, tol=1e-9, rtol=1e-10, atol=1e-10) finalcoords = ret.coords print(ret.coords) # np.savetxt(foldpath + '/coords_of_minimum.txt', finalcoords, delimiter=',') print(ret) # print(ret.coords) # print(ret2.coords) # print(ret2.coords-ret.coords) print(finalcoords) E, V, H = potential.getEnergyGradientHessian(finalcoords) print(np.linalg.eigvals(H), "all eigenvalues")
def setup_inverse_power(SysParams, radii, box_length): """ sets up the inverse power potential Parameters ---------- SysParams : Enum Parameters for the system we wish to study radii : np.ndarray radii of particles in the system box_length : float length of the box """ # check that the setup is for a dict if type(SysParams) is not dict: raise TypeError("system parameters need to be in dictionary form") box_vec = np.array([box_length] * int(SysParams["ndim"])) print(SysParams["use_cell_lists"]) potential = InversePower( SysParams["power"], SysParams["eps"], use_cell_lists=SysParams["use_cell_lists"], ndim=SysParams["ndim"], radii=radii * 1.0, boxvec=box_vec, ) return potential
def test_same_minima_InversePower(self): nparticles = 32 hs_radii = 0.05 * np.random.randn(nparticles) + 1 volpart = np.sum(4. / 3. * np.pi * hs_radii**3) phi = 0.7 boxl = (volpart / phi)**(1 / 3.) boxv = [boxl, boxl, boxl] coords = np.random.rand(nparticles * 3) * boxl ncellx_scale = get_ncellsx_scale(np.ones(nparticles), boxv) bdim = 3 pot_cellists = InversePower(2.5, 1, hs_radii, ndim=3, boxvec=boxv, use_cell_lists=True, ncellx_scale=ncellx_scale) pot_no_cellists = InversePower(2.5, 1, hs_radii, ndim=3, boxvec=boxv, use_cell_lists=False, ncellx_scale=ncellx_scale) nsteps = 1000 tol = 1e-5 res_cell_lists = lbfgs_cpp(coords, pot_cellists, nsteps=nsteps, tol=tol) res_no_cell_lists = lbfgs_cpp(coords, pot_no_cellists, nsteps=nsteps, tol=tol) fcoords_cell_lists = res_cell_lists.coords fcoords_no_cell_lists = res_no_cell_lists.coords # self.assertEqual(fcoords_no_cell_lists,fcoords_cell_lists) self.assertTrue(np.all(fcoords_no_cell_lists == fcoords_cell_lists))
def quench_single_inverse_power(coord_file_name, foldpath, sub_fold_name, optimizer, opt_param_dict): """ figures out the minimum correspoding to a set of particle coords Parameters ---------- coord_file_name: string name of the path to the coordinates foldername: str folder definining the run sub_fold_name: name of subfolder where the run data is stored optimizer: optimizer quench opt_param_dict: dict dictionary of parameters for the optimizer """ sysparams = load_params(foldpath) # path to quench coords quench_coords_path = (foldpath + "/" + sub_fold_name + "/" + "ensemble/" + coord_file_name) quench_coords = np.loadtxt(quench_coords_path) radii = get_hs_radii(foldpath, sub_fold_name) box_length = get_box_length(radii, sysparams.ndim.value, sysparams.phi.value) boxv = [box_length] * sysparams.ndim.value ncellx_scale = get_ncellsx_scale(radii, boxv) potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=radii * 1.0, boxvec=boxv, ) boxv = [box_length] * sysparams.ndim.value # ncellx_scale = get_ncellsx_scale(radii, boxv) print(potential.getEnergy(quench_coords)) ret = optimizer(quench_coords, potential, **opt_param_dict) try: ret = optimizer(quench_coords, potential, **opt_param_dict) except: print("exception occured") # if exception occurs, treat as failure. this is for rattlers # not enough failures occur that it would make a difference to not just assume this never happens # but we shoudl switch this out # but jic return (quench_coords, False, 0, 0, 0, 0, 0) # This exists because some runs don't have hessian evaluations try: ret["nhev"] except: ret["nhev"] = 0 # mixed optimizer statistics try: ret["n_phase_1"] except: ret["n_phase_1"] = 0 # mixed optimizer statistics try: ret["n_phase_2"] except: ret["n_phase_2"] = 0 print(ret.coords - quench_coords) print(opt_param_dict) results = ( ret.coords, ret.success, ret.nfev, ret.nsteps, ret.nhev, ret.n_phase_1, ret.n_phase_2, ) print(quench_coords_path) return results
0.13492935, 5.55656566, 5.19310115, 5.80610666, 6.53090015, 5.3332587, 3.07972527, 5.20893375, ] test_radii = np.array(test_radii) test_coords = np.array(test_coords) box_length = 6.673592625078725 potential = InversePower( 2.5, 1.0, use_cell_lists=False, ndim=2.0, radii=test_radii, boxvec=[box_length, box_length], ) test_gradient = np.copy(test_coords) potential.getEnergyGradientInPlace(test_coords, test_gradient) grad = potential.getEnergyGradient(test_coords) print(test_gradient) print(grad) # np.savetxt('energy.csv', np.array([potential.getEnergy(test_coords)]), delimiter=',') # np.savetxt('gradient.csv', potential.getEnergyGradient(test_coords)[1], delimiter=',') # np.savetxt('hessian.csv', potential.getEnergyGradientHessian(test_coords)[2], delimiter=',')
def get_potential(self): return InversePower(self.power, self.eps, self.radii, boxvec=self.boxvec, **self.potential_kwargs)
3.16224709493039, ] ctol = 1e-2 ndim = 2 base_dir = "/home/praharsh/Dropbox/research/bv-libraries/basinerror/datainv" foldnameInversePower = "ndim=2phi=0.9seed=0n_part=16r1=1.0r2=1.4rstd1=0.05rstd2=0.06999999999999999use_cell_lists=0power=2.5eps=1.0" data_loc = base_dir + "/" + foldnameInversePower minima_database_path = data_loc + "minima_database.npy" (hs_radii, initial_coords, box_length) = load_secondary_params(data_loc) sysparams = load_params(data_loc) potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=hs_radii * 1.0, boxvec=[box_length, box_length], ) minima_container_debug = CheckSameMinimum( ctol, ndim, boxl=box_length, minimalist_max_len=2000, minima_database_location=minima_database_path, update_database=True, rattler_check=True, potential=potential, hs_radii=hs_radii, )
def compare_runs_2d(fnames, foldpath, subfoldname, run_a, run_b, ctol): """ compares runs on points with names fnames between runs done with 2 minima find routines run_a and run_b Args: fnames filenames run_a run a run_b run b Returns: percentage of minima that are the same """ # TODO: replace this sysparams = load_params(foldpath) radii = get_hs_radii(foldpath, subfoldname) box_length = get_box_length(radii, sysparams.ndim.value, sysparams.phi.value) subfoldpath = foldpath + "/" + subfoldname data_path_a = subfoldpath + "/" + run_a data_path_b = subfoldpath + "/" + run_b potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=radii * 1.0, boxvec=[box_length, box_length], ) minima_checker = CheckSameMinimum(ctol, dim=2, boxl=box_length, hs_radii=radii, potential=potential) same_minimum_check_l = [] for fname in fnames: print(fname) minimum_a = np.loadtxt(data_path_a + "/" + fname, delimiter=",") minimum_b = np.loadtxt(data_path_b + "/" + fname, delimiter=",") boxed_minimum_a = minima_checker.box_reshape_coords(minimum_a) boxed_minimum_b = minima_checker.box_reshape_coords(minimum_b) # get first index that is not a rattler rattlers_exist, rattlers = minima_checker._find_rattlers(minimum_a) print(rattlers) # number of non rattlers to ensure we're not in a fluid state n_non_rattlers = np.count_nonzero(rattlers) # only do calculations if all particles aren't rattlers if n_non_rattlers != 0: first_non_rattler = (np.argwhere(rattlers != 0).T)[0, 0] # TODO: rewrite the CheckSameMinimum function # load and make sure the particle being aligned is not a rattler later # we're choosing -1 because that's always going to be of radius 1.4 # particle aligned_minimum_b = minima_checker.align_structures( boxed_minimum_a, boxed_minimum_b, part_ind=first_non_rattler) same_minimum_check = minima_checker.check_same_structure( aligned_minimum_b, boxed_minimum_a, rattlers) same_minimum_check_l.append(same_minimum_check) fraction_same_minimum = np.mean(same_minimum_check_l) print(fraction_same_minimum) return fraction_same_minimum
def map_binary_inversepower( foldername, particle_coords, optimizer, parameter_dict, random_coord_0=0, random_coord_1=-1, z=0, ): """ Finds whether a point defined by particle_coord on the meshgrid correspond to a minimum or not for a 2d case. """ foldpath = BASE_DIRECTORY + "/" + foldername # import params sysparams = load_params(foldpath) (hs_radii, initial_coords, box_length) = load_secondary_params(foldpath) assert sysparams.ndim.value == 2 minimum_coords = np.loadtxt(foldpath + "/coords_of_minimum.txt", delimiter=",") quench_coords = initial_coords.copy() if len(quench_coords) == 16: quench_coords = ( quench_coords + particle_coords[0] * VEC_8_0 + particle_coords[1] * VEC_8_1 + z * VEC_8_2 ) elif len(quench_coords) == 32: quench_coords = ( quench_coords + particle_coords[0] * VEC_16_0 + particle_coords[1] * VEC_16_1 + z * VEC_16_2 ) elif len(quench_coords) == 64: quench_coords = ( quench_coords + particle_coords[0] * VEC_16_0 + particle_coords[1] * VEC_16_1 + z * VEC_16_2 ) else: raise Exception("error other random coords have not been generated") print(quench_coords, "quench") # print(quench_coords, 'quench coords') # box length box_length = float(box_length) boxv = [box_length] * sysparams.ndim.value ncellx_scale = get_ncellsx_scale(hs_radii, boxv) potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=hs_radii * 1.0, boxvec=boxv, ) # ret = quench_mixed_optimizer(potential, # quench_coords, # make sure right coords are being passed # T=10, # step=1, # nsteps=100000, # conv_tol=1e-8, # tol=1e-6, rtol=1e-4, atol=1e-4) # ret = quench_steepest( # potential, # quench_coords, # make sure right coords are being passed # nsteps=2000000, # stepsize=5e-3, # for steepest descent step size should be small # tol=1e-4) # ret = quench_cvode_opt(potential, quench_coords, tol=1e-6, rtol=1e-4, atol=1e-4) try: ret = optimizer(quench_coords, potential, **parameter_dict) except: print(quench_coords, "failed here") print(initial_coords, "coords") print(len(quench_coords)) raise Exception("failure") # ret = lbfgs_cpp(quench_coords, potential, tol=1e-8, M=1) # This exists because some runs don't have hessian evaluations try: ret["nhev"] except: ret["nhev"] = 0 coordarg = 0 results = (ret.coords, ret.success, coordarg, ret.nfev, ret.nsteps, ret.nhev) # the reason the potential is being passed is because quench coords needs the potential to figure out what to do return results
def map_pointset_loop_xy( foldname, pointset, optimizer, parameter_dict, ctol=1e-2, ndim=2, use_minima_database=True, minima_database_path=None, coord_arg_0=0, coord_arg_1=1, z=0, ): """ Checks a bunch of points if they match to a minimum by using a for loop """ is_same_minimum_list = [] resultlist = [] foldpath = BASE_DIRECTORY + "/" + foldname sysparams = load_params(foldpath) (hs_radii, initial_coords, box_length) = load_secondary_params(foldpath) minimum_coords = np.loadtxt(foldpath + "/coords_of_minimum.txt", delimiter=",") # Initialize CheckSameMinimum potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=hs_radii * 1.0, boxvec=[box_length, box_length], ) minima_container = CheckSameMinimum( ctol, ndim, boxl=box_length, minimalist_max_len=200000, minima_database_location=minima_database_path, update_database=True, rattler_check=True, potential=potential, hs_radii=hs_radii, ) if use_minima_database == True: try: minima_container.minimalist = [ minima_container.box_reshape_coords(x) for x in np.load(minima_database_path) ] except: print("warning no minima data found. generating") minima_container.minimalist = [ # minima_container.box_reshape_coords(minimum_coords) ] nfevlist = [] nstepslist = [] nhevlist = [] for index, point in enumerate(pointset): res = map_binary_inversepower( foldname, point, optimizer, parameter_dict, random_coord_0=coord_arg_0, random_coord_1=coord_arg_1, z=z, ) minima_container.add_minimum(res[0], point, res[2]) # print(index) # print(minima_container.nrattlermin, 'nrattlermin') # print(minima_container.nfluidstates, 'nfluidstates') nfevlist.append(res[3]) nstepslist.append(res[4]) nhevlist.append(res[5]) # print(np.average(nfevlist), 'number of function evaluations') # print(np.average(nstepslist), 'number of steps') # print(np.average(nstepslist), 'number of steps') # print(np.average(nhevlist), "number of hessian evaluations") # print(minima_container.orderparamlist) foldpathdata = foldpath + "/" + QUENCH_FOLDER_NAME + "/z_data_30_l6/" + str(z) os.makedirs(foldpathdata, exist_ok=True) minima_container.dump_map(foldpathdata) run_diagnostics = {} run_diagnostics["nfev"] = float(np.average(nfevlist)) run_diagnostics["nhev"] = float(np.average(nhevlist)) run_diagnostics["nsteps"] = float(np.average(nstepslist)) # print(minima_container.initial_coords_list) # print(minima_container.orderparamlist) # print(minima_container.orderparamlist) return run_diagnostics, is_same_minimum_list, resultlist
def map_binary_inversepower( foldername, particle_coords, optimizer, parameter_dict, random_coord_0=0, random_coord_1=-1, z=0, index=None, mesh_length=None, ): """ Finds whether a point defined by particle_coord on the meshgrid correspond to a minimum or not for a 2d case. """ foldpath = BASE_DIRECTORY + "/" + foldername # import params sysparams = load_params(foldpath) (hs_radii, initial_coords, box_length) = load_secondary_params(foldpath) assert sysparams.ndim.value == 2 quench_coords = initial_coords.copy() print("initial_coords", initial_coords) print(particle_coords[0], particle_coords[1], "vector coefficients as passed") print("z value") quench_coords = (quench_coords + particle_coords[0] * VEC_16_0 + particle_coords[1] * VEC_16_1 + z * VEC_16_2) # TODO: save this as a unit meshgrid # print(quench_coords, 'quench coords') # box length box_length = float(box_length) boxv = [box_length] * sysparams.ndim.value ncellx_scale = get_ncellsx_scale(hs_radii, boxv) print(hs_radii) potential = InversePower( sysparams.power.value, sysparams.eps.value, use_cell_lists=False, ndim=sysparams.ndim.value, radii=hs_radii * 1.0, boxvec=boxv, ) # save potential parameters # writing this out since Enum to dict conversion does not give the mapping we want potential_params_fname = "potential_params.yaml" potential_param_dict = { "ndim": sysparams.ndim.value, "phi": sysparams.phi.value, "seed": 0, "n_part": sysparams.n_part.value, "r1": sysparams.r1.value, "r2": sysparams.r2.value, "rstd1": sysparams.rstd1.value, "rstd2": sysparams.rstd2.value, "use_cell_lists": int(False), "power": sysparams.power.value, "eps": sysparams.eps.value, } param_str = generate_param_str_from_dict(potential_param_dict) # make directory to emulate structure by refactored code emulation_folder = COMPARE_FOLDER_NAME + "/" + param_str # add README to emulation folder os.makedirs(emulation_folder, exist_ok=True) with open(COMPARE_FOLDER_NAME + "/README.org", "w") as f: f.write(" \#+AUTHOR Praharsh Suryadevara .\n") f.write("* Read First.") f.write( "This dirctory has been auto-generated by old code before refactoring. Do not change.\n" ) # emulates path of the refactored code ensemble_folder_path = emulation_folder + "/ensemble/random_plane" os.makedirs(ensemble_folder_path, exist_ok=True) # 0 to emulate the addition of seed sec_param_folder_path = emulation_folder + "/sec_params/0" os.makedirs(sec_param_folder_path, exist_ok=True) old_code_results_folder_path = emulation_folder + "/old_data" os.makedirs(old_code_results_folder_path, exist_ok=True) with open(emulation_folder + "/params.yaml", "w") as param_file: yaml.dump(potential_param_dict, param_file) opt_param_fname = "minima_finder_params.yaml" with open(emulation_folder + "/" + opt_param_fname, "w") as param_file: yaml.dump(parameter_dict, param_file) initial_coords_fname = str(index) + ".txt" np.savetxt(ensemble_folder_path + "/" + initial_coords_fname, quench_coords, delimiter=",") mesh_coords_fname = str(index) + "_mesh.txt" np.savetxt(ensemble_folder_path + "/" + mesh_coords_fname, particle_coords, delimiter=",") if mesh_length is not None: # 2 *[particle_coords[0], particle_coords[1]]/mesh_length -0.5 form our unit mesh_grid # centered around [0, 0] mesh_coords = (2 * np.array([particle_coords[0], particle_coords[1]]) / mesh_length - 0.5) mesh_coords_fname = str(index) + "_mesh.txt" np.savetxt(ensemble_folder_path + "/" + mesh_coords_fname, mesh_coords, delimiter=",") np.savetxt( sec_param_folder_path + "/" + "initial_coords.txt", initial_coords, delimiter=",", ) np.savetxt( sec_param_folder_path + "/" + "box_length.txt", np.array([box_length]), delimiter=",", ) np.savetxt(sec_param_folder_path + "/" + "hs_radii.txt", hs_radii, delimiter=",") # ret = quench_mixed_optimizer(potential, # quench_coords, # make sure right coords are being passed # T=10, # step=1, # nsteps=100000, # conv_tol=1e-8, # tol=1e-6, rtol=1e-4, atol=1e-4) # ret = quench_steepest( # potential, # quench_coords, # make sure right coords are being passed # nsteps=2000000, # stepsize=5e-3, # for steepest descent step size should be small # tol=1e-4) # ret = quench_cvode_opt(potential, quench_coords, tol=1e-6, rtol=1e-4, atol=1e-4) try: ret = optimizer(quench_coords, potential, **parameter_dict) except: raise Exception("failure") # ret = lbfgs_cpp(quench_coords, potential, tol=1e-8, M=1) # This exists because some runs don't have hessian evaluations try: ret["nhev"] except: ret["nhev"] = 0 coordarg = 0 final_coords = ret["coords"] final_coords_fname = str(index) + "_coords.txt" np.savetxt( old_code_results_folder_path + "/" + final_coords_fname, final_coords, delimiter=",", ) energy, grad, hess = potential.getEnergyGradientHessian(final_coords) hessian_fname = str(index) + "_hessian.txt" np.savetxt(old_code_results_folder_path + "/" + hessian_fname, hess, delimiter=",") grad_fname = str(index) + "_grad.txt" np.savetxt(old_code_results_folder_path + "/" + grad_fname, grad, delimiter=",") last_step_fname = str(index) + "_step.txt" # np.savetxt(old_code_results_folder_path + '/' + # last_step_fname, ret['step'], delimiter=',') # check that the minimum hessian eigenvalue is positive # print out the eigenvector corresponding to it eigvals, eigvecs = np.linalg.eigh(hess) print(eigvals[1]) print(eigvecs[:, 1]) # step_in_eigvec_basis = np.matmul(eigvecs.T, ret['step']) # step_in_eigvec_basis_normalized = step_in_eigvec_basis/np.linalg.norm(step_in_eigvec_basis) # -1e-15 is to avoid numerical issues if np.min(eigvals) < -1e-3: print("minimum Eigenvalue: ", np.min(eigvals)) print("Eigenvalues: ", eigvals) raise Exception("negative eigenvalue") # save heuristics as a dict results = ( ret.coords, ret.success, coordarg, ret.nfev, ret.nsteps, ret.nhev, eigvecs, ) # simplified dictionary since we're only using the success variable res_dict = { "success": bool(ret.success), "nsteps": ret.nsteps, "energy": ret.energy, "nfev": ret.nfev, } # print("-------------------------------------------------steppp", step_in_eigvec_basis_normalized) # print("eigenvalues", eigvals) yaml_fname = str(index) + ".yaml" # save heuristics as yaml with open(old_code_results_folder_path + "/" + yaml_fname, "w") as f: yaml.dump(res_dict, f) print(ret.nsteps, "nsteps") # the reason the potential is being passed is because quench coords needs the potential to figure out what to do return results