class Optimizer(): def __init__(self, input_file, N): self.input_constraints = Constraint(input_file) #print(self.input_constraints.get_ndim()) #print(self.input_constraints.get_example()) #print(self.input_constraints.get_constraints()) #exam = np.array(list(self.input_constraints.get_example()), dtype=float) #print(self.input_constraints.apply(exam)) self.x = self.sample(N) self.get_output() def sample(self, N): count = 0 ndim = int(self.input_constraints.get_ndim()) x = np.empty((0, ndim)) while (count < int(N)): n_samples = int(N) * 10 smpls = lhs(ndim, samples=n_samples) for i in range(len(smpls)): if self.input_constraints.apply(smpls[i]) and (count < int(N)): #print(smpls[i]) x = np.append(x, np.array([smpls[i]]), axis=0) count += 1 print(count) print(x.shape) return x def get_output(self): return self.x
class Sampler: def __init__(self, filename, max_points, max_time): self.constraint = Constraint(filename) self.n_dim = self.constraint.n_dim self.example = self.constraint.example self.max_points = max_points self.max_time = max_time def test_inside(self, x): if np.any(np.less(x, 0.)): return False if np.any(np.greater(x, 1.)): return False return self.constraint.apply(x) def line_search(self, x, direction): tiny = 1e-6 low, high = 0., np.sqrt(self.n_dim) + tiny for _ in range(20): middle = 0.5 * (low + high) inside = self.test_inside(x + middle * direction) if inside: low = middle else: high = middle return low def random_direction(self): vector = np.random.normal(size=self.n_dim) return vector / np.linalg.norm(vector) def hit_and_run(self): assert self.test_inside(self.example) points = [np.array(self.example)] start_time = time.time() while len(points) < self.max_points and time.time( ) - start_time < self.max_time: direction = self.random_direction() factor = self.line_search(points[-1], direction) if factor > 0.: new_point = points[-1] + np.random.uniform( ) * factor * direction if self.test_inside(new_point): points.append(new_point) return points
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 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 validate_output_file(self, constraints_file_name, points_file_name, expected): """ Validates output file against constraint file to see if required number of points are available. :param string constraints_file_name: path to a file that contains the constraints :param string points_file_name: path to a file that contains the vectors to be validated :param int expected: Number of points that are expected in this file """ self.log.info( f'Running validation: {constraints_file_name} <-> {points_file_name}' ) # Return if constraints or points files are not found. try: constraints = Constraint(constraints_file_name) except FileNotFoundError: self.log.critical( f'Constraints file {constraints_file_name} not found. Skipping validation...' ) return try: points_file = open(points_file_name, 'r') except FileNotFoundError: self.log.critical( f'Points file {points_file_name} not found. Skipping validation...' ) return # Counters for number of points that were generated, passed, failed, generated = 0 passed = 0 failed = 0 for itr, line in enumerate(points_file): x = [float(_) for _ in line.strip().split(" ")] # Log how many points have been checked. if itr != 0 and (itr % pow(10, floor(log10(itr + 1))) == 0): self.log.debug(f'Checked {itr}') # Count number of points generated/passed/failed generated += 1 try: if constraints.apply(x): passed += 1 else: self.log.warning(f'Point outside constraints: {x}') failed += 1 except: self.log.error(f'{sys.exc_info()[1]}, point: {x}') points_file.close() # Points file summary self.log.info(f'{generated} generated, {expected} expected') self.log.info(f'{passed} passed, {failed} failed') if generated != expected: self.log.warning(f'Unexpected number of points') if failed > 0: self.log.warning(f'{failed} points failed') if passed == expected or passed == generated: self.log.info(f'All points are valid') self.log.info( f'Validated {constraints_file_name} <-> {points_file_name}') self.log.info(f'-- Validation complete -- ') return
class Solution(): def __init__(self, fname, outfile, n_results): self.con = Constraint(fname) self.num_x = self.con.n_dim self.n_results = n_results self.outfile = outfile with open(self.outfile, 'w') as f: f.write(" ".join(map(str, self.con.example))) f.write("\n") self.ineq_cons = { 'type': 'ineq', 'fun': lambda x: self.con.eval_con(x.tolist()) } bound = [0.0, 1.0] self.bounds = np.asarray([bound] * self.num_x) # determining the magnitude of the largest initial point max_initial = max(self.con.example) if max_initial == 0.0: self.alpha = 1.0 else: self.alpha = 1.0 / max_initial def solve(self): x0_all = np.random.random_sample( (self.n_results * 2, self.num_x)) / self.alpha output = [] cnt = 0 for i in range(len(x0_all)): x0 = x0_all[i, :] if self.con.apply(x0.tolist()): x_feasible = x0 else: try: res = self.optimize_feasible(x0) x_feasible = res.x if res.status != 0 or any(x_feasible < 0.0) or any( x_feasible > 1.0) or list(x_feasible) in output: continue except: continue # if self.con.apply(x_feasible.tolist()): # print "True" with open(self.outfile, 'a') as f: f.write(" ".join(map(str, x_feasible))) f.write("\n") output.append(list(x_feasible)) cnt += 1 if cnt == self.n_results: break return output def optimize_feasible(self, x0): res = optimize.minimize(self.f, x0, method='SLSQP', constraints=[self.ineq_cons], options={ 'ftol': 1e-8, 'disp': False }, bounds=self.bounds) return res def f(self, x): constr = self.con.eval_con(x.tolist()) constr[np.where(constr > 0)] = 0 return np.sum(np.square(constr)) def constraint(self, x): constr = self.con.eval_con(x.tolist()) return constr
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())