def sampler(input_file, output_file, n_result): ct = Constraint(input_file) ndim = ct.get_ndim() current_results = [] while len(current_results) < n_result: res = np.random.random(ndim) res = (res / sum(res) * sum(ct.get_example())).round(5) if not ct.apply(res): continue current_results.append(res) print('example:', ct.get_example()) print('res:', res) with open(output_file, 'a') as f: for l, el in enumerate(current_results): string = ' '.join(map(str, el)) # for item in string: f.write(string) f.write('\n') return current_results
def main(argv): if len(sys.argv) < 3: print( 'Please provide 3 command line arguments (e.g. input_filename, output_filename, n_results' ) exit(-1) in_filename = '' out_filename = '' niteration = 0 in_filename = sys.argv[1] out_filename = sys.argv[2] niteration = int(sys.argv[3]) c = Constraint(in_filename) v = c.get_example() print(v) n = c.get_ndim() #this is the chromosome size for each population print(n) # print(c.apply([0.5, 1.0, 0.0, 0.5])) s = 300 #population size ga = Genetic( s, n, in_filename ) #initializes ga type object with populaton size, chromosome size, input file name p = ga.get_population() print(p) print(ga.cal_pop_fitness()) temp_solution = ga.eval_ga(niteration) # print(temp_solution) # write result to the output with open(out_filename, 'w') as filehandle: for item in temp_solution: s = " ".join(str(e) for e in item) # print(s) l = s # l = item print(l) filehandle.write('%s\n' % l) filehandle.close()
def get_constraints(input_file): """reads the input file and creates an instance of the Constraint class """ # create a new instance of the Constraint class by reading input_file # catch several errors: file not found, first two lines (number of # dimensions and starting vector) not formatted correctly, or syntax # error in the constraints try: space = Constraint(input_file) except FileNotFoundError: sys.exit("Error: input file not found") except ValueError: sys.exit("Error: input file formatted improperly") except SyntaxError: sys.exit("Error: syntax error in constraints") # get the example point and make sure it has the correct dimensionality example = space.get_example() if len(example) < space.get_ndim(): sys.exit("Error: example point does not have enough dimensions") # check and make sure the example point actually satisfies all of the # constraints. This additionally serves to make sure the constraints # are specified correctly try: check_example = space.apply(example) except IndexError: sys.exit("Error: invalid constraints") except NameError: sys.exit("Error: invalid constraints") # if space.apply(example) returned false, then throw an error if not check_example: sys.exit("Error: example point is invalid") return space
def main(): # Obtain input arguments parser = argparse.ArgumentParser(description='Process inputs to sampler') parser.add_argument('input_file', default=None, type=str) parser.add_argument('output_file', default="output.txt", type=str) parser.add_argument('N', default=1000, type=int) parser.add_argument('--plot_bool', action="store_true") # Parse input arguments args = parser.parse_args() input_file = args.input_file output_file = args.output_file N = args.N plot_bool = args.plot_bool np.random.seed(0) # Load file and the corresponding constraint functions and valid example if not path.isfile(input_file) and input_file: raise ValueError('Input file does not exist') elif input_file: constraint = Constraint(input_file) x0 = np.array(constraint.get_example()) constraints = constraint.eval_constraints constraint_bool = constraint.apply constraint_bools = constraint.apply_list else: # Used for local testing constraints = func_constraints constraint_bool = func_constraints_bool x0 = x0 # Obtain bounds of input space from which initial sample guesses will # be uniformly drawn bounds = get_bounds(x0, constraint_bools) # Find valid uniformly distributed samples with constrained SMC N_star = int(N * 1.1) run = RunSMC(N=N_star, bounds=bounds, type="constrained_smc", tau_T=1e7, constraints=constraints) x, x0 = run.get_x(), run.get_x0() # Evaluate validity. uniqueness, and spread of results # Subsample result acc, x_valid = get_accuracy(x, constraint_bool) idx_x, idx_x_valid = np.arange(x.shape[0]), np.arange(x_valid.shape[0]) x = x_valid[np.random.choice(idx_x_valid, N, replace=False)] if x_valid.shape[0] >= N else \ x[np.random.choice(idx_x, N, replace=False)] std = np.std(x, axis=0) uniq_nums = np.unique(x, axis=0).shape[0] print('accuracy: {acc} std: {std} unique candidates: {uniq}'.format( acc=acc, std=std, uniq=uniq_nums)) # Save output and plot if 2D and plot_bool np.savetxt(output_file, x, delimiter=' ') if x.shape[1] == 2 and plot_bool: plt.plot(x0[:, 0], x0[:, 1], 'o', x[:, 0], x[:, 1], '*') plt.show()
class Generator: """ Generator class to generate output_file with required number of points that satisfy constraints in input_file. """ def __init__(self, input_file_name): """ Construct a Generator object and set up the log files. :param string input_file_name: Name of the constraints file """ # Setup class logger setup_logger('log_generator.log') self.log = logging.getLogger('log_generator.log') # Set up the constraints self.input_file_name = input_file_name try: self.constraints = Constraint(self.input_file_name) except FileNotFoundError: self.log.critical( f'Constraints file not found: {self.input_file_name}') else: self.log.info(f'Setup Generator for {self.input_file_name}') # Set and queue to hold and explore the required points self.point_set = set() self.points_queue = deque() # Generate_valid_points uses a form of breadth first search to generate n points satisfying the constraints defined in input_file_name. def generate_valid_points(self, n_points, min_step_size=1E-30): """ Generate required number of points that satisfy constraints. :param int n_points: Required number of points. :param float min_step_size: Optional minimum step size (default = 1E-30) for exploration. """ # Return if constraint file is unavailable try: self.constraints except NameError: self.log.critical( f'Constraints file not found {self.input_file_name} not found. Terminating generation...' ) return self.log.info( f'Points required: {n_points}, min_step_size: {min_step_size}') self.log.info( f'Constraints file: {self.input_file_name}, Dimension: {self.constraints.get_ndim()}, Starting point: {self.constraints.get_example()}' ) # Cast as a tuple since immutability is required to put into a set. self.point_set.add(tuple(self.constraints.get_example())) # Initial step size for exploration. step_size = 1.0 # Run while more points are required. while len(self.point_set) < n_points: # Add all valid points to the queue for exploration. for _ in self.point_set: self.points_queue.append(_) # Counter to count points found at a given step size. n_new_points = 0 # Run while the queue exists and more points are required. while self.points_queue and len(self.point_set) < n_points: # Explore outward from each point in the queue and add the found valid points to the queue and set. current_point = self.points_queue.popleft() n_new_points += self.explore_point(current_point, step_size, n_points, self.constraints) # End inner while loop: Done with finding points at given step size self.log.debug( f'Found: {n_new_points} with step size: {step_size}, total in set: {len(self.point_set)}' ) # Decrease step_size and search again. step_size /= 2 if step_size < min_step_size: self.log.warning( f'Step size is too small: {step_size}, breaking search') break # End outer while loop: Done with finding required number of points. self.log.info(f'Points found: {len(self.point_set)}') self.log.info(f'-- Generation complete -- ') return def explore_point(self, current_point, step_size, n_points, constraints): """ Explore outward from the current point in all dimensions with a given step size. Points that satisfy constraints are added to the queue and the point_set. The function returns the number of valid points found from current point. :param tuple current_point: Starting point of exploration :param float step_size: extent of exploration :param int n_points: required number of points :param Constraint constraints: set of constraints to satisfy """ found_points = 0 for i_dim in range(len(current_point)): for direction in [-1, +1]: # Update the coordinates, use round() to remove floating point errors, and cast as tuple for hash-abilty. next_point = list(current_point) round_to_digit = max( self.n_digits_after_decimal(next_point[i_dim]), self.n_digits_after_decimal(step_size)) next_point[i_dim] = round( next_point[i_dim] + (direction * step_size), round_to_digit) next_point = tuple(next_point) try: # If next_point is within the unit hypercube, meets constraints, and is not already explored, add to queue and set. if self.unit_cube_check(next_point) and constraints.apply( next_point) and next_point not in self.point_set: self.points_queue.append(next_point) self.point_set.add(next_point) found_points += 1 # ZeroDivisionError exception is logged as a warning and the script continues. except ZeroDivisionError: self.log.warning( f'{sys.exc_info()[1]}, point: {next_point}') # Unexpected exceptions are logged as errors and the script continues. except: self.log.error(f'{sys.exc_info()}, point: {next_point}') # Return if the number of required points are found. if len(self.point_set) == n_points: return found_points return found_points def write_to_file(self, output_file_name): """ Setup output file and write coordinates to it. :param string output_file_name: Name of the file to write the generated points """ # If constraint file was not found, point_set is empty so there is nothing to write. if len(self.point_set) == 0: self.log.error( f'No points generated for {self.input_file_name}. Terminating writing to {output_file_name}...' ) return self.log.info(f'Writing: {self.input_file_name} -> {output_file_name}') # Warn if file already exists and will be overwritten. if path.exists(output_file_name): self.log.warning( f'{output_file_name} already exists, overwriting file') # Open file for writing and write set of points to it. # Use an iterator to remove the new line character from the last line. with open(output_file_name, "w") as output_file: itr = 0 new_line = '\n' for point in self.point_set: itr += 1 if itr == len(self.point_set): new_line = '' output_file.write(" ".join(map(str, point)) + new_line) self.log.info(f'Written {itr} lines.') self.log.info(f'-- Writing complete -- ') return def unit_cube_check(self, x): """ Check if the given vector is within the unit hypercube. :param tuple x: Object that is used to represent the vector """ for _ in x: if _ > 1 or _ < 0: return False return True def n_digits_after_decimal(self, x): """ Return the number of digits after the decimal in x. :param float x: input number x """ return len(str(x).split(".")[-1])
class SCMC(): """Use sequentially constrained Monte Carlo method to sample given constrained domains uniformly Methods ------- write_ouput: write the final sample in given path get_correctness: return the correctness of the final state get_history: return a List, the history all samples in the sequential diffusion process plot_results: scatter plot the results along two arbitrary axes params ------ comp1, int: first axis (h) comp2, int: second axis (v) n_iter, int: if want history instead of final state print_constraints: print the original constraints """ def __init__(self, input_path, n_results, beta_max=10**4, p_beta=1, p_rw_step=0, track_correctness=False, threshold=.999): self.input_path = input_path self.constraints = Constraint(input_path) constraints_funcs = self.constraints.get_functions() self.n_dim = self.constraints.get_ndim() self.n_results = n_results self.beta_max = beta_max self.p_beta = p_beta self.p_rw_step = p_rw_step #call sampling method scmc i_sample = init_sample(self.n_dim, self.n_results, self.constraints.bounds, self.constraints.get_example()) self.i_samples = [] self.i_samples.append(i_sample) self.histories = [] self.correctnesses = [] print(len(constraints_funcs)) for i in range(1, len(constraints_funcs) + 1): history, correctness = scmc( self.n_dim, self.n_results, self.i_samples[i - 1], constraints_funcs[0:i], beta_max, self.constraints.bounds, p_beta, p_rw_step, track_correctness=track_correctness, given_example=self.constraints.get_example(), threshold=threshold) self.i_samples.append(history[-1]) self.histories.append(history) self.correctnesses.append(correctness) self.results = self.histories[-1][-1] # self.history, self.correctness = scmc(self.n_dim, self.n_results, i_sample ,constraints_funcs, beta_max, self.constraints.bounds, # p_beta,p_rw_step, # track_correctness=track_correctness, # given_example = self.constraints.get_example()) # self.results = self.history[-1] # self.history, self.correctness = scmc(self.n_dim, self.n_results, constraints_funcs, beta_max, self.constraints.bounds, # p_beta,p_rw_step, # track_correctness=track_correctness, # given_example = self.constraints.get_example()) # self.results = self.history[-1] # self.write_ouput(output_path) def write_output(self, output_path): """ save the sample to a output_path """ np.savetxt(output_path, self.results) def get_correctness(self): """ get correctness """ correctness = [self.constraints.apply(x) for x in self.results] correctness = sum(correctness) / self.n_results return correctness def get_history(self): return self.history def get_results(self): """ get the sample """ return self.results def plot_results(self, comp1, comp2, n_iter=None): """ Plot the sample in x[comp1],x[comp2] """ if n_iter is None: sample = self.results else: sample = self.history[n_iter - 1] plt.figure() plt.scatter(sample[:, comp1], sample[:, comp2]) plt.xlim(0, 1) plt.ylim(0, 1) def plot_all_axis(self, n_iter=None): n_dim = self.n_dim for i in range(n_dim): for j in range(i + 1, n_dim): self.plot_results(i, j, n_iter) plt.xlabel('x_{}'.format(i)) plt.ylabel('x_{}'.format(j)) def print_constraints(self): print(self.constraints.get_exprs_string())