def run(self, graph, trainset, validset, train_config, device, verbose=False): assert isinstance(graph, ProgramGraph) current = copy.deepcopy(graph.root_node) current_avg_f_score = float('inf') best_program = None best_total_cost = float('inf') best_programs_list = [] num_children_trained = 0 start_time = time.time() while not graph.is_fully_symbolic(current.program): log_and_print("CURRENT program has avg fscore {:.4f}: {}".format( current_avg_f_score, print_program(current.program, ignore_constants=(not verbose)))) children = graph.get_all_children(current, in_enumeration=True) children_mapping = { print_program(child.program, ignore_constants=True) : child for child in children } children_scores = { key : [] for key in children_mapping.keys() } costs = [child.cost for child in children] for i in range(self.num_mc_samples): child = random.choices(children, weights=costs)[0] sample = self.mc_sample(graph, child) assert graph.is_fully_symbolic(sample.program) log_and_print("Training sample program: {}".format(print_program(sample.program, ignore_constants=(not verbose)))) sample_score = execute_and_train(sample.program, validset, trainset, train_config, graph.output_type, graph.output_size, neural=False, device=device) num_children_trained += 1 log_and_print("{} total children trained".format(num_children_trained)) sample_f_score = sample.cost + sample_score children_scores[print_program(child.program, ignore_constants=True)].append(sample_f_score) if sample_f_score < best_total_cost: best_program = copy.deepcopy(sample.program) best_total_cost = sample_f_score best_programs_list.append({ "program" : best_program, "struct_cost" : sample.cost, "score" : sample_score, "path_cost" : sample_f_score, "time" : time.time()-start_time }) log_and_print("New BEST program found:") print_program_dict(best_programs_list[-1]) # (Naive) selection operation children_scores = { key : sum(val)/len(val) if len(val) > 0 else float('inf') for key,val in children_scores.items() } best_child_name = min(children_scores, key=children_scores.get) current = children_mapping[best_child_name] current_avg_f_score = children_scores[best_child_name] for key,val in children_scores.items(): log_and_print("Avg score {:.4f} for child {}".format(val,key)) log_and_print("SELECTING {} as best child node\n".format(best_child_name)) log_and_print("DEBUG: time since start is {:.3f}\n".format(time.time()-start_time)) return best_programs_list
def run(self, graph, trainset, validset, train_config, device, verbose=False): assert isinstance(graph, ProgramGraph) symbolic_programs = [] enum_depth = 1 while len(symbolic_programs) < self.max_num_programs: print("DEBUG: starting enumerative synthesis with depth {}".format(enum_depth)) symbolic_programs = self.enumerate2depth(graph, enum_depth) print("DEBUG: {} programs found".format(len(symbolic_programs))) enum_depth += 1 if enum_depth > graph.max_depth: break log_and_print("Symbolic Synthesis: generated {}/{} symbolic programs from candidate program.".format( len(symbolic_programs), self.max_num_programs)) total_eval = min(self.max_num_programs, len(symbolic_programs)) symbolic_programs.sort(key=lambda x: x["struct_cost"]) symbolic_programs = symbolic_programs[:total_eval] best_program = None best_total_cost = float('inf') best_programs_list = [] start_time = time.time() num_programs_trained = 1 for prog_dict in symbolic_programs: child_start_time = time.time() candidate = prog_dict["program"] log_and_print("Training candidate program ({}/{}) {}".format( num_programs_trained, total_eval, print_program(candidate, ignore_constants=(not verbose)))) num_programs_trained += 1 score = execute_and_train(candidate, validset, trainset, train_config, graph.output_type, graph.output_size, neural=False, device=device) total_cost = score + prog_dict["struct_cost"] log_and_print("Structural cost is {} with structural penalty {}".format(prog_dict["struct_cost"], graph.penalty)) log_and_print("Time to train child {:.3f}".format(time.time()-child_start_time)) log_and_print("Total time elapsed is: {:.3f}".format(time.time()-start_time)) if total_cost < best_total_cost: best_program = copy.deepcopy(prog_dict["program"]) best_total_cost = total_cost prog_dict["score"] = score prog_dict["path_cost"] = total_cost prog_dict["time"] = time.time()-start_time best_programs_list.append(prog_dict) log_and_print("New BEST program found:") print_program_dict(best_programs_list[-1]) return best_programs_list
def run_near(self, model, num_iter): train_config = { 'lr': self.learning_rate, 'neural_epochs': self.neural_epochs, 'symbolic_epochs': self.symbolic_epochs, 'optimizer': optim.Adam, 'lossfxn': nn.CrossEntropyLoss(), #todo 'evalfxn': label_correctness, 'num_labels': self.num_labels } # Initialize program graph starting from trained NN program_graph = ProgramGraph(model, DSL_DICT, CUSTOM_EDGE_COSTS, self.input_type, self.output_type, self.input_size, self.output_size, self.max_num_units, self.min_num_units, self.max_num_children, self.max_depth, self.penalty, ite_beta=self.ite_beta) # Initialize algorithm algorithm = ASTAR_NEAR(frontier_capacity=self.frontier_capacity) best_programs = algorithm.run(program_graph, self.batched_trainset, self.validset, train_config, self.device) if self.algorithm == "rnn": # special case for RNN baseline best_program = best_programs else: # Print all best programs found log_and_print("\n") log_and_print("BEST programs found:") for item in best_programs: print_program_dict(item) best_program = best_programs[-1]["program"] # Save best program self.program_path = os.path.join(self.save_path, "program_%d.p" % num_iter) pickle.dump(best_program, open(self.program_path, "wb"))
def run(self, graph, trainset, validset, train_config, device, verbose=False): assert isinstance(graph, ProgramGraph) self.input_size = graph.input_size self.output_size = graph.output_size best_program = None best_score = float('inf') best_total = float('inf') best_programs_list = [] start_time = time.time() log_and_print("Generating all programs up to specified depth.") all_generated_programs = self.enumerative_synthesis( graph, self.max_enum_depth) random.shuffle(all_generated_programs) current_population = all_generated_programs[:self.population_size] total_trained_programs = 0 def crossover_operation(listofprogramdicts): new_prog_dict = {} parents = random.choices(listofprogramdicts, k=2) prog_dict1, prog_dict2 = parents[0], parents[1] xover1 = random.randint(1, prog_dict1['depth']) xover2 = random.randint(2, prog_dict2['depth']) print('DEBUG: trying new crossover') new_program, crossed_over = self.crossover_helper( prog_dict1['program'], prog_dict2['program'], xover1, xover2) if crossed_over: log_and_print("Crossing over the following programs:") log_and_print( print_program(prog_dict1['program'], ignore_constants=True)) log_and_print( print_program(prog_dict2['program'], ignore_constants=True)) new_prog_dict["program"] = new_program new_prog_dict["struct_cost"], new_prog_dict[ "depth"] = graph.compute_program_cost(new_program) log_and_print("Result has structural cost {:.4f}:".format( new_prog_dict["struct_cost"])) log_and_print( print_program(new_prog_dict['program'], ignore_constants=True)) return new_prog_dict else: return None def mutation_operation(mod_prog_dict): new_prog_dict = {} mutation_point = random.randrange(1, mod_prog_dict['depth']) new_prog_dict['program'] = self.mutation_helper( graph, mod_prog_dict['program'], mod_prog_dict['depth'], mutation_point, max_enumeration_depth=self.max_enum_depth) new_prog_dict["struct_cost"], new_prog_dict[ "depth"] = graph.compute_program_cost(new_prog_dict['program']) return new_prog_dict for gen_idx in range(self.num_gens): #evaluation operation: train each program and evaluate it. log_and_print( "Training generation {}'s population of programs.".format( gen_idx + 1)) for programdict in current_population: total_trained_programs += 1 child_start_time = time.time() log_and_print("Training candidate program ({}/{}) {}".format( total_trained_programs, self.total_eval, print_program(programdict['program'], ignore_constants=(not verbose)))) score = execute_and_train(programdict['program'], validset, trainset, train_config, graph.output_type, graph.output_size, neural=False, device=device) log_and_print( "Structural cost is {} with structural penalty {}".format( programdict["struct_cost"], graph.penalty)) log_and_print( "Time to train child {:.3f}".format(time.time() - child_start_time)) log_and_print("Total time elapsed is: {}".format(time.time() - start_time)) programdict["score"] = score programdict["path_cost"] = score + programdict["struct_cost"] programdict["time"] = time.time() - start_time if programdict["path_cost"] < best_total: best_program = copy.deepcopy(programdict["program"]) best_total = score + programdict["struct_cost"] best_score = score best_cost = programdict["struct_cost"] best_programs_list.append(copy.deepcopy(programdict)) log_and_print("New BEST program found:") print_program_dict(best_programs_list[-1]) if total_trained_programs > self.total_eval: break #select the best programs based on cost + score. current_population.sort(key=lambda x: x["path_cost"]) selected_population = current_population[:self.selection_size] #perform crossover on the selected population crossed_population = [] log_and_print("Beginning crossover operation.") while len(crossed_population) < self.population_size: new_prog_dict = crossover_operation(selected_population) if new_prog_dict is not None: crossed_population.append(new_prog_dict) #perform mutations on the crossed population current_population = [] for crossed_prog_dict in crossed_population: if random.random() < self.mutation_prob: log_and_print("Mutating program.") current_population.append( mutation_operation(crossed_prog_dict)) else: current_population.append(crossed_prog_dict) return best_programs_list
def run_near(self): # print(self.device) train_config = { 'lr' : self.learning_rate, 'neural_epochs' : self.neural_epochs, 'symbolic_epochs' : self.symbolic_epochs, 'optimizer' : optim.Adam, 'lossfxn' : nn.CrossEntropyLoss(weight=self.loss_weight), #todo 'evalfxn' : label_correctness, 'num_labels' : self.num_labels } near_input_type = self.hole_node[0].input_type near_output_type = self.hole_node[0].output_type near_input_size = self.hole_node[0].input_size near_output_size = self.hole_node[0].output_size # Initialize program graph starting from trained NN program_graph = ProgramGraph(DSL_DICT, CUSTOM_EDGE_COSTS, near_input_type, near_output_type, near_input_size, near_output_size, self.max_num_units, self.min_num_units, self.max_num_children, self.max_depth, self.penalty, ite_beta=self.ite_beta) # Initialize algorithm algorithm = ASTAR_NEAR(frontier_capacity=self.frontier_capacity) best_programs = algorithm.run(self.timestamp, self.base_program_name, self.hole_node_ind, program_graph, self.batched_trainset, self.validset, train_config, self.device) best_program_str = [] if self.algorithm == "rnn": # special case for RNN baseline best_program = best_programs else: # Print all best programs found log_and_print("\n") log_and_print("BEST programs found:") for item in best_programs: program_struct = print_program(item["program"], ignore_constants=True) program_info = "struct_cost {:.4f} | score {:.4f} | path_cost {:.4f} | time {:.4f}".format( item["struct_cost"], item["score"], item["path_cost"], item["time"]) best_program_str.append((program_struct, program_info)) print_program_dict(item) best_program = best_programs[-1]["program"] # Save best programs f = open(os.path.join(self.save_path, "best_programs.txt"),"w") f.write( str(best_program_str) ) f.close() self.program_path = os.path.join(self.save_path, "subprogram.p") pickle.dump(best_program, open(self.program_path, "wb")) self.full_path = os.path.join(self.save_path, "fullprogram.p") if self.device == 'cpu': base_program = CPU_Unpickler(open("%s.p" % self.base_program_name, "rb")).load() else: base_program = pickle.load(open("%s.p" % self.base_program_name, "rb")) curr_level = 0 l = [] traverse(base_program.submodules,l) curr_program = base_program.submodules change_key(base_program.submodules, [], self.hole_node_ind, best_program.submodules["program"]) pickle.dump(base_program, open(self.full_path, "wb")) # Save parameters f = open(os.path.join(self.save_path, "parameters.txt"),"w") parameters = ['input_type', 'output_type', 'input_size', 'output_size', 'num_labels', 'neural_units', 'max_num_units', 'min_num_units', 'max_num_children', 'max_depth', 'penalty', 'ite_beta', 'train_valid_split', 'normalize', 'batch_size', 'learning_rate', 'neural_epochs', 'symbolic_epochs', 'lossfxn', 'class_weights', 'num_iter', 'num_f_epochs', 'algorithm', 'frontier_capacity', 'initial_depth', 'performance_multiplier', 'depth_bias', 'exponent_bias', 'num_mc_samples', 'max_num_programs', 'population_size', 'selection_size', 'num_gens', 'total_eval', 'mutation_prob', 'max_enum_depth', 'exp_id', 'base_program_name', 'hole_node_ind'] for p in parameters: f.write( p + ': ' + str(self.__dict__[p]) + '\n' ) f.close()
def run(self, graph, trainset, validset, train_config, device, verbose=False): assert isinstance(graph, ProgramGraph) log_and_print("Training root program ...") current = copy.deepcopy(graph.root_node) initial_score = execute_and_train(current.program, validset, trainset, train_config, graph.output_type, graph.output_size, neural=True, device=device) log_and_print( "Initial training complete. Score from program is {:.4f} \n". format(1 - initial_score)) # Branch-and-bound search with iterative deepening current_depth = self.initial_depth current_f_score = float('inf') order = 0 frontier = ProgramNodeFrontier(capacity=self.frontier_capacity) next_frontier = ProgramNodeFrontier(capacity=self.frontier_capacity) num_children_trained = 0 start_time = time.time() best_program = None best_total_cost = float('inf') best_programs_list = [] log_and_print("Starting iterative deepening with depth {}\n".format( current_depth)) while current_depth <= graph.max_depth: log_and_print("CURRENT program has fscore {:.4f}: {}".format( current_f_score, print_program(current.program, ignore_constants=(not verbose)))) log_and_print("Current depth of program is {}".format( current.depth)) log_and_print("Creating children for current node/program") log_and_print("Total time elapsed is {:.3f}".format(time.time() - start_time)) children_nodes = graph.get_all_children(current) # prune if more than self.max_num_children if len(children_nodes) > graph.max_num_children: log_and_print("Sampling {}/{} children".format( graph.max_num_children, len(children_nodes))) children_nodes = random.sample( children_nodes, k=graph.max_num_children) # sample without replacement log_and_print("{} total children to train for current node".format( len(children_nodes))) child_tuples = [] for child_node in children_nodes: child_start_time = time.time() log_and_print("Training child program: {}".format( print_program(child_node.program, ignore_constants=(not verbose)))) is_neural = not graph.is_fully_symbolic(child_node.program) child_node.score = execute_and_train(child_node.program, validset, trainset, train_config, graph.output_type, graph.output_size, neural=is_neural, device=device) log_and_print( "Time to train child {:.3f}".format(time.time() - child_start_time)) num_children_trained += 1 log_and_print( "{} total children trained".format(num_children_trained)) child_node.parent = current child_node.children = [] order -= 1 child_node.order = order # insert order of exploration as tiebreaker for equivalent f-scores # computing path costs (f_scores) child_f_score = child_node.cost + child_node.score # cost + heuristic log_and_print("DEBUG: f-score {}".format(child_f_score)) current.children.append(child_node) child_tuples.append((child_f_score, order, child_node)) if not is_neural and child_f_score < best_total_cost: best_program = copy.deepcopy(child_node.program) best_total_cost = child_f_score best_programs_list.append({ "program": best_program, "struct_cost": child_node.cost, "score": child_node.score, "path_cost": child_f_score, "time": time.time() - start_time }) log_and_print("New BEST program found:") print_program_dict(best_programs_list[-1]) # find next current among children, from best to worst nextfound = False child_tuples.sort(key=lambda x: x[0]) for child_tuple in child_tuples: child = child_tuple[2] if graph.is_fully_symbolic(child.program): continue # don't want to expand symbolic programs (no children) elif child.depth >= current_depth: next_frontier.add(child_tuple) else: if not nextfound: nextfound = True # first child program that's not symbolic and within current_depth current_f_score, current_order, current = child_tuple log_and_print( "Found program among children: {} with f_score {}". format( print_program(current.program, ignore_constants=(not verbose)), current_f_score)) else: frontier.add(child_tuple) # put the rest onto frontier # find next node in frontier if not nextfound: frontier.sort(tup_idx=1) # DFS order log_and_print("Frontier length is: {}".format(len(frontier))) original_depth = current.depth while len(frontier) > 0 and not nextfound: current_f_score, current_order, current = frontier.pop( 0, sort_fscores=False) # DFS order if current_f_score < self.bound_modify( best_total_cost, original_depth, current.depth): nextfound = True log_and_print( "Found program in frontier: {} with f_score {}". format( print_program(current.program, ignore_constants=(not verbose)), current_f_score)) else: log_and_print( "PRUNE from frontier: {} with f_score {}".format( print_program(current.program, ignore_constants=(not verbose)), current_f_score)) log_and_print("Frontier length is now {}".format( len(frontier))) # frontier is empty, go to next stage of iterative deepening if not nextfound: assert len(frontier) == 0 log_and_print("Empty frontier, moving to next depth level") log_and_print( "DEBUG: time since start is {:.3f}\n".format(time.time() - start_time)) current_depth += 1 if current_depth > graph.max_depth: log_and_print("Max depth {} reached. Exiting.\n".format( graph.max_depth)) break elif len(next_frontier) == 0: log_and_print("Next frontier is empty. Exiting.\n") break else: log_and_print( "Starting iterative deepening with depth {}\n".format( current_depth)) frontier = copy.deepcopy(next_frontier) next_frontier = ProgramNodeFrontier( capacity=self.frontier_capacity) current_f_score, current_order, current = frontier.pop(0) if best_program is None: log_and_print("ERROR: no program found") return best_programs_list
total_eval=args.total_eval, mutation_prob=args.mutation_prob, max_enum_depth=args.max_enum_depth) elif args.algorithm == "rnn": algorithm = RNN_BASELINE() else: raise NotImplementedError # Run program learning algorithm best_programs = algorithm.run(program_graph, batched_trainset, validset, train_config, device) if args.algorithm == "rnn": # special case for RNN baseline best_program = best_programs else: # Print all best programs found log_and_print("\n") log_and_print("BEST programs found:") for item in best_programs: print_program_dict(item) best_program = best_programs[-1]["program"] # Save best program pickle.dump(best_program, open(os.path.join(save_path, "program.p"), "wb")) # Evaluate best program on test set test_set_eval(best_program, testset, args.output_type, args.output_size, args.num_labels, device) log_and_print("ALGORITHM END \n\n")
def run(self, graph, trainset, validset, train_config, device, verbose=False, trainset_neural=None): assert isinstance(graph, ProgramGraph) log_and_print("Training root program ...") current = copy.deepcopy(graph.root_node) dataset = trainset_neural if trainset_neural is not None else trainset initial_score = execute_and_train(current.program, validset, dataset, train_config, graph.output_type, graph.output_size, neural=True, device=device) log_and_print( "Initial training complete. Score from program is {:.4f} \n". format(1 - initial_score)) order = 0 frontier = ProgramNodeFrontier(capacity=self.frontier_capacity) frontier.add((float('inf'), order, current)) num_children_trained = 0 start_time = time.time() best_program = None best_total_cost = float('inf') best_programs_list = [] while len(frontier) != 0: current_f_score, _, current = frontier.pop(0) log_and_print("CURRENT program has fscore {:.4f}: {}".format( current_f_score, print_program(current.program, ignore_constants=(not verbose)))) log_and_print("Current depth of program is {}".format( current.depth)) log_and_print("Creating children for current node/program") children_nodes = graph.get_all_children(current) # prune if more than self.max_num_children if len(children_nodes) > graph.max_num_children: children_nodes = random.sample( children_nodes, k=graph.max_num_children) # sample without replacement log_and_print("{} total children to train for current node".format( len(children_nodes))) for child_node in children_nodes: child_start_time = time.time() log_and_print("Training child program: {}".format( print_program(child_node.program, ignore_constants=(not verbose)))) is_neural = not graph.is_fully_symbolic(child_node.program) dataset = trainset_neural if ( is_neural and trainset_neural is not None) else trainset child_node.score = execute_and_train(child_node.program, validset, dataset, train_config, graph.output_type, graph.output_size, neural=is_neural, device=device) log_and_print( "Time to train child {:.3f}".format(time.time() - child_start_time)) num_children_trained += 1 log_and_print( "{} total children trained".format(num_children_trained)) child_node.parent = current child_node.children = [] order -= 1 child_node.order = order # insert order of exploration as tiebreaker for equivalent f-scores current.children.append(child_node) # computing path costs (f_scores) child_f_score = child_node.cost + child_node.score # cost + heuristic log_and_print("DEBUG: f-score {}".format(child_f_score)) if not is_neural and child_f_score < best_total_cost: best_program = copy.deepcopy(child_node.program) best_total_cost = child_f_score best_programs_list.append({ "program": best_program, "struct_cost": child_node.cost, "score": child_node.score, "path_cost": child_f_score, "time": time.time() - start_time }) log_and_print("New BEST program found:") print_program_dict(best_programs_list[-1]) if is_neural: assert child_node.depth < graph.max_depth child_tuple = (child_f_score, order, child_node) frontier.add(child_tuple) # clean up frontier frontier.sort(tup_idx=0) while len(frontier) > 0 and frontier.peek(-1)[0] > best_total_cost: frontier.pop(-1) log_and_print("Frontier length is: {}".format(len(frontier))) log_and_print("Total time elapsed is {:.3f}".format(time.time() - start_time)) if best_program is None: log_and_print("ERROR: no program found") return best_programs_list
def run(self, timestamp, base_program_name, hole_node_ind, graph, trainset, validset, train_config, device, verbose=False): assert isinstance(graph, ProgramGraph) log_and_print("Training root program ...") current = copy.deepcopy(graph.root_node) initial_score, l, m = execute_and_train_with_full(base_program_name, hole_node_ind, current.program, validset, trainset, train_config, graph.output_type, graph.output_size, neural=True, device=device) # print("initial losses:") # print(l) # print("initial f1:") # print(m) log_and_print("Initial training complete. Score from program is {:.4f} \n".format(1 - initial_score)) order = 0 frontier = ProgramNodeFrontier(capacity=self.frontier_capacity) #mcheng priority queue frontier.add((float('inf'), order, current)) num_children_trained = 0 start_time = time.time() best_program = None best_total_cost = float('inf') best_programs_list = [] # if not os.path.exists(timestamp): # os.makedirs(timestamp) while len(frontier) != 0: current_f_score, _, current = frontier.pop(0) log_and_print("CURRENT program has fscore {:.4f}: {}".format( current_f_score, print_program(current.program, ignore_constants=(not verbose)))) log_and_print("Current depth of program is {}".format(current.depth)) log_and_print("Creating children for current node/program") children_nodes = graph.get_all_children(current) # print(children_nodes) # prune if more than self.max_num_children truncated_children = [] symbolic_children = [] if len(children_nodes) > graph.max_num_children: #keep all neural ones for c in children_nodes: is_neural = not graph.is_fully_symbolic(c.program) if is_neural: truncated_children.append(c) else: symbolic_children.append(c) n = len(truncated_children) if n < graph.max_num_children: #get weights for each child # if print_program(current.program).split('(')[-1].split(')')[0] == 'AtomToAtomModule': # weights = [] # # print(weights_dict) # for c in symbolic_children: # diff_node = print_program(c.program).split('(')[-2] # # print(print_program(c.program)) # # print(diff_node) # # try: # # weights.append(weights_dict[diff_node]) # # except IndexError: # # print('tutu') # # weights.append(0) # else: #weight equally # weights = [1] * len(symbolic_children) # #make into probabilities # sum_h = sum(weights) # probs = [i/sum_h for i in weights] # print(probs) picked_children = np.random.choice(symbolic_children, graph.max_num_children - n) #p=probs truncated_children.extend(picked_children) # truncated_children.extend(random.sample(symbolic_children, k=graph.max_num_children-n)) # sample without replacement else: print(truncated_children) truncated_children = random.sample(truncated_children, k=graph.max_num_children) children_nodes = truncated_children print(children_nodes) #todo if theres more neural children than alloewd.... log_and_print("{} total children to train for current node".format(len(children_nodes))) for child_node in children_nodes: child_start_time = time.time() log_and_print("Training child program: {}".format(print_program(child_node.program, ignore_constants=(not verbose)))) is_neural = not graph.is_fully_symbolic(child_node.program) #mcheng is not complete child_node.score, l, m = execute_and_train_with_full(base_program_name, hole_node_ind, child_node.program, validset, trainset, train_config, graph.output_type, graph.output_size, neural=is_neural, device=device) ## print losses and 1-f1 score for training # plt.close() # plt.figure() # plt.plot(l[2:]) # plt.title("losses %s" % print_program(child_node.program, ignore_constants=(not verbose))) # plt.savefig("%s/losses_%s.png" % (timestamp,print_program(child_node.program, ignore_constants=(not verbose)))) # plt.close() # plt.figure() # plt.plot(m[2:]) # plt.title("f1 %s" %print_program(child_node.program, ignore_constants=(not verbose))) # plt.savefig("%s/f1_%s.png" % (timestamp,print_program(child_node.program, ignore_constants=(not verbose)))) log_and_print("Time to train child {:.3f}".format(time.time() - child_start_time)) num_children_trained += 1 log_and_print("{} total children trained".format(num_children_trained)) child_node.parent = current child_node.children = [] order -= 1 child_node.order = order # insert order of exploration as tiebreaker for equivalent f-scores current.children.append(child_node) # computing path costs (f_scores) child_f_score = child_node.cost + child_node.score # cost + heuristic log_and_print("DEBUG: f-score {}".format(child_f_score)) if not is_neural and child_f_score < best_total_cost: best_program = copy.deepcopy(child_node.program) best_total_cost = child_f_score best_programs_list.append({ "program" : best_program, "struct_cost" : child_node.cost, "score" : child_node.score, "path_cost" : child_f_score, "time" : time.time()-start_time }) log_and_print("New BEST program found:") print_program_dict(best_programs_list[-1]) if is_neural: assert child_node.depth < graph.max_depth child_tuple = (child_f_score, order, child_node) frontier.add(child_tuple) # clean up frontier frontier.sort(tup_idx=0) while len(frontier) > 0 and frontier.peek(-1)[0] > best_total_cost: frontier.pop(-1) log_and_print("Frontier length is: {}".format(len(frontier))) log_and_print("Total time elapsed is {:.3f}".format(time.time()-start_time)) if best_program is None: log_and_print("ERROR: no program found") return best_programs_list #todo look at train fn, todo understand why some of the nodes are neural #starts with a neural fn.