Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    def run(self, graph, trainset, validset, train_config, device, verbose=False):
        assert isinstance(graph, ProgramGraph)

        log_and_print("Training RNN baseline with {} LSTM units ...".format(graph.max_num_units))
        current = copy.deepcopy(graph.root_node)
        score = execute_and_train(current.program, validset, trainset, train_config, 
            graph.output_type, graph.output_size, neural=True, device=device)
        log_and_print("Score of RNN is {:.4f}".format(1-score))
        
        return current.program
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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
Exemplo n.º 6
0
    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