示例#1
0
    def __init__(self,
                 f,
                 allowed_functions=None,
                 selection_strategy=None,
                 init_list=None,
                 depth=None,
                 build_strategy='grow'):  # build_strategy: "grow"/"full"
        self.f = f
        self.rtype = f.rtype

        allowed_children = self.f.allowed_children()
        if allowed_functions is not None:
            allowed_children = [[
                child for child in child_list if child in allowed_functions
            ] for child_list in allowed_children]
        type_table = grow_type_table if build_strategy == 'grow' else full_type_table
        allowed_children = [[
            child for child in child_list
            if child in type_table[depth][child.rtype]
        ] for child_list in allowed_children]
        if not all(allowed_children):
            raise UnsatisfiableType(
                "{} has a parameter that cannot be satisfied.".format(
                    self.f.__name__))

        if init_list is not None:
            self.num_children = len(init_list)
            self.children = []
            for i, (fn, sublist) in enumerate(init_list):
                if fn not in allowed_children[i]:
                    convert_fn = lookup_convert(
                        f.__getattribute__('__params')[i], fn.rtype)
                    if convert_fn is not None:
                        self.children.append(
                            Node(convert_fn, init_list=[(fn, sublist)]))
                    else:
                        raise UnsatisfiableType(
                            "Invalid initialization for {}. {} expected, {} ({}) provided."
                            .format(self.f.__name__, self.rtype, fn.__name__,
                                    fn.rtype))
                else:
                    self.children.append(Node(fn, init_list=sublist))
            return

        if selection_strategy is not None:
            child_choices = selection_strategy(
                parent=self.f,
                children=allowed_children,
            )
        else:
            child_choices = (random.choice(child_list)
                             for child_list in allowed_children)
        self.children = [
            Node(choice,
                 allowed_functions=allowed_functions,
                 selection_strategy=selection_strategy,
                 depth=depth - 1,
                 build_strategy=build_strategy) for choice in child_choices
        ]
        self.num_children = len(self.children)
示例#2
0
def optimize(scoring_function,
             population_size=250,
             iterations=25,
             build_tree=build_tree,
             next_generation=next_generation,
             show_scores=True):
    print("Creating initial population of {}.".format(population_size))
    sys.stdout.flush()

    population = []
    for __ in xrange(population_size):
        try:
            tree = build_tree_to_requirements(scoring_function)
            population.append(tree)
        except UnsatisfiableType:
            raise UnsatisfiableType(
                "Could not meet input requirements. Found only {} satisfying trees."
                .format(len(population)))
    best_tree = [random.choice(population)]
    early_stop = []

    def score_callback(iteration, scores):
        if not show_scores:
            return

        non_failure_scores = [
            score for score in scores.values() if score != -sys.maxsize
        ]
        try:
            average_score = sum(non_failure_scores) / len(non_failure_scores)
        except ZeroDivisionError:
            average_score = -sys.maxsize
        best_score = max(scores.values())

        best_tree.append(max(scores, key=scores.get))

        print("Iteration {}:\tBest: {:.2f}\tAverage: {:.2f}".format(
            iteration + 1,
            best_score,
            average_score,
        ))
        sys.stdout.flush()

        if best_score == getattr(scoring_function, '__max_score', None):
            early_stop.append(True)

    print("Optimizing...")
    with recursion_limit(600):
        for iteration in xrange(iterations):
            callback = functools.partial(score_callback, iteration)
            population = next_generation(population,
                                         scoring_function,
                                         score_callback=callback)
            if early_stop:
                break

    best_tree = max(best_tree, key=scoring_function)
    return best_tree
示例#3
0
def find_functions(return_type, allowed_functions=None, convert=True):
    functions = lookup_rtype(return_type, convert)
    if allowed_functions is None:
        return functions
    allowable = frozenset(functions) & frozenset(allowed_functions)
    if not allowable:
        raise UnsatisfiableType("No allowable functions satisfying {}.".format(
            (prettify_converted_type if not convert else str)(return_type)))
    return list(allowable)
示例#4
0
def build_tree_to_requirements(scoring_function):
    params = getattr(scoring_function, '__params', ())
    if len(params) != 1:
        raise ValueError("Scoring function must accept a single parameter.")
    return_type, = params

    for __ in xrange(9999):
        with recursion_limit(500):
            tree = build_tree(return_type, convert=False)
        requirements = getattr(scoring_function, 'required_inputs', ())
        if not all(req in tree for req in requirements):
            continue
        return tree

    raise UnsatisfiableType("Could not meet input requirements.")
示例#5
0
def crossover(first_tree, second_tree=None):
    first_tree_info = get_tree_info(first_tree)
    if second_tree is None:
        sending_tree_info, receiving_tree_info = first_tree_info, first_tree_info
    else:
        sending_tree_info, receiving_tree_info = (first_tree_info, get_tree_info(second_tree))[::random.choice((-1, 1))]
    mutual_rtypes = list(frozenset(sending_tree_info.nodes_by_rtype) & frozenset(receiving_tree_info.nodes_by_rtype))
    if not mutual_rtypes:
        raise UnsatisfiableType("Trees are not compatible.")
    chosen_rtype = random.choice(mutual_rtypes)
    chosen_node = random.choice(receiving_tree_info.nodes_by_rtype[chosen_rtype])
    chosen_replacement = random.choice(sending_tree_info.nodes_by_rtype[chosen_rtype])
    chosen_node.parent.children[chosen_node.index] = copy.deepcopy(chosen_replacement.node)
    if second_tree is None:
        return first_tree
    return first_tree if first_tree_info is receiving_tree_info else second_tree
示例#6
0
 def __init__(self, f, allowed_functions=None, selection_strategy=None):
     self.f = f
     self.rtype = f.rtype
     
     allowed_children = self.f.allowed_children()
     if allowed_functions is not None:
         allowed_children = [
             [child for child in child_list if child in allowed_functions] 
             for child_list in 
             allowed_children
         ]
     if not all(allowed_children):
         raise UnsatisfiableType(
             "{} has a parameter that cannot be satisfied.".format(self.f.__name__)
         )
     if selection_strategy is not None:
         child_choices = selection_strategy(
             parent=self.f,
             children=allowed_children,
         )
     else:
         child_choices = (
             random.choice(child_list) 
             for child_list in 
             allowed_children
         )
     self.children = [
         Node(
             choice,
             allowed_functions=allowed_functions,
             selection_strategy=selection_strategy,
         ) 
         for choice in 
         child_choices
     ]
     self.num_children = len(self.children)