예제 #1
0
    def recursions(self):
        parent = c_pred("parent", 2)
        ancestor = c_pred("ancestor", 2)

        hs = TopDownHypothesisSpace(primitives=[
            lambda x: plain_extension(x, parent, connected_clauses=True)
        ],
                                    head_constructor=ancestor,
                                    recursive_procedures=True)

        cls = hs.get_current_candidate()
        cls2 = hs.expand(cls[1])
        print(cls2)
예제 #2
0
    def process_expansions(
            self, examples: Task, exps: typing.Sequence[Clause],
            hypothesis_space: TopDownHypothesisSpace
    ) -> typing.Sequence[Clause]:
        # eliminate every clause with more body literals than allowed
        exps = [cl for cl in exps if len(cl) <= self._max_body_literals]

        new_exps = []
        # check if every clause has solutions
        for cl in exps:
            y = self.evaluate(task, cl)
            if y[0] > 0:
                new_exps.append(cl)
            else:
                hypothesis_space.remove(cl)
        return new_exps
예제 #3
0
    def _learn_one_clause(self, examples: Task,
                          hypothesis_space: TopDownHypothesisSpace) -> Clause:
        """
        Learns a single clause

        Returns a clause
        """
        # reset the search space
        hypothesis_space.reset_pointer()

        # empty the pool just in case
        self.initialise_pool()

        # put initial candidates into the pool
        self.put_into_pool(hypothesis_space.get_current_candidate())
        current_cand = None
        score = -100

        while current_cand is None or (
                len(self._candidate_pool) > 0
                and not self.stop_inner_search(score, examples, current_cand)):
            # get first candidate from the pool
            current_cand = self.get_from_pool()

            # expand the candidate
            _ = hypothesis_space.expand(current_cand)
            # this is important: .expand() method returns candidates only the first time it is called;
            #     if the same node is expanded the second time, it returns the empty list
            #     it is safer than to use the .get_successors_of method
            exps = hypothesis_space.get_successors_of(current_cand)
            exps = self.process_expansions(examples, exps, hypothesis_space)
            # add into pool
            self.put_into_pool(exps)

            score = self.evaluate(examples, current_cand, hypothesis_space)

        if self._print:
            print(f"- New clause: {current_cand}")
            print(
                f"- Candidates has value {round(score,2)} for metric '{self._eval_fn.name()}'"
            )
        return current_cand
    def process_expansions(
            self, examples: Task, exps: typing.Sequence[Clause],
            hypothesis_space: TopDownHypothesisSpace
    ) -> typing.Sequence[Clause]:
        # eliminate every clause with more body literals than allowed
        exps = [cl for cl in exps if len(cl) <= self._max_body_literals]

        # check if every clause has solutions
        exps = [(cl, self._solver.has_solution(*cl.get_body().get_literals()))
                for cl in exps]
        new_exps = []

        for ind in range(len(exps)):
            if exps[ind][1]:
                # keep it if it has solutions
                new_exps.append(exps[ind][0])
            else:
                # remove from hypothesis space if it does not
                hypothesis_space.remove(exps[ind][0])

        return new_exps
예제 #5
0
    def bottom_up(self):
        a = c_pred("a", 2)
        b = c_pred("b", 2)
        c = c_pred("c", 1)
        h = c_pred("h", 2)

        cl = h("X", "Y") <= a("X", "Z") & b("Z", "Y") & c("X")

        bc = BottomClauseExpansion(cl)

        hs = TopDownHypothesisSpace(primitives=[lambda x: bc.expand(x)],
                                    head_constructor=h)

        cls = hs.get_current_candidate()
        assert len(cls) == 3

        exps = hs.expand(cls[1])
        assert len(exps) == 2

        exps2 = hs.expand(exps[0])
        assert len(exps2) == 4
예제 #6
0
    def top_down_limited(self):
        grandparent = c_pred("grandparent", 2)
        father = c_pred("father", 2)
        mother = c_pred("mother", 2)

        hs = TopDownHypothesisSpace(
            primitives=[
                lambda x: plain_extension(x, father, connected_clauses=False),
                lambda x: plain_extension(x, mother, connected_clauses=False)
            ],
            head_constructor=grandparent,
            expansion_hooks_keep=[lambda x, y: connected_clause(x, y)],
            expansion_hooks_reject=[lambda x, y: has_singleton_vars(x, y)])

        current_cand = hs.get_current_candidate()
        assert len(current_cand) == 3

        expansions = hs.expand(current_cand[1])
        assert len(expansions) == 6

        expansion2 = hs.expand(expansions[1])
        assert len(expansion2) == 16
예제 #7
0
def train_task(task_id: string,
               pos_multiplier: int,
               neg_example_offset: int,
               nn_amount: int,
               pos=None,
               neg=None):
    # Load needed files
    bk, predicates = createKnowledge(
        "../inputfiles/StringTransformations_BackgroundKnowledge.pl", task_id)

    if pos is None and neg is None:
        pos, neg = generate_examples(task_id, pos_multiplier,
                                     neg_example_offset)

    task = Task(positive_examples=pos, negative_examples=neg)

    # Calculate predicates
    total_predicates = []
    filtered_predicates = []
    for predicate in predicates:
        if predicate.name not in ["s", task_id
                                  ] and predicate not in filtered_predicates:
            total_predicates.append(lambda x, pred=predicate: plain_extension(
                x, pred, connected_clauses=True))
            filtered_predicates.append(predicate)

    # create the hypothesis space
    hs = TopDownHypothesisSpace(
        primitives=total_predicates,
        head_constructor=c_pred("test_task", 1),
        recursive_procedures=True,
        expansion_hooks_keep=[
            lambda x, y: connected_clause(x, y),
            lambda x, y: only_1_pred_for_1_var(x, y),
            lambda x, y: head_first(x, y)
        ],
        expansion_hooks_reject=[  # lambda x, y: has_singleton_vars(x, y),
            # Singleton-vars constraint is reduced to this constraint
            lambda x, y: has_not_previous_output_as_input(x, y),  # Strict
            # lambda x, y: has_new_input(x, y), # Not as strict
            # lambda x, y: has_unexplained_last_var(x, y), # For the 'write' predicate
            lambda x, y: has_unexplained_last_var_strict(
                x, y),  # Strict version of above
            lambda x, y: has_duplicated_literal(x, y),
            lambda x, y: has_g1_same_vars_in_literal(x, y),
            lambda x, y: has_duplicated_var_set(x, y),
            lambda x, y: has_double_recursion(x, y),
            lambda x, y: has_endless_recursion(x, y)
        ])

    learner = NeuralSearcher1(solver_instance=prolog,
                              primitives=filtered_predicates,
                              model_location="../utility/Saved_model_covered",
                              max_body_literals=10,
                              amount_chosen_from_nn=nn_amount,
                              filter_amount=30,
                              threshold=0.1)

    # Try to learn the program
    program, ss = learner.learn(
        task, "../inputfiles/StringTransformations_BackgroundKnowledge.pl", hs)
    print(program)

    return ss
예제 #8
0
    def _learn_one_clause(self, examples: Task, hypothesis_space: TopDownHypothesisSpace) -> Clause:
        """
        Learns a single clause

        Returns a clause
        """
        # reset the search space
        hypothesis_space.reset_pointer()

        # empty the pool just in case
        self.initialise_pool()

        # put initial candidates into the pool
        self.put_into_pool([Triplet(hypothesis_space.get_current_candidate()[0]).get_tuple()])
        current_cand = None
        first = True
        score = -100

        while current_cand is None or (
                self._candidate_pool.qsize() > 0 and not self.stop_inner_search(score, examples, current_cand)):
            # get first candidate from the pool
            current_cand = self.get_from_pool()

            if first:
                self.example_weights[current_cand] = self.get_initial_weights(examples)
                first = False

            print("-------------------------------------------------------")
            print("CURRENT CANDIDATE: ")
            print("\t ", current_cand)
            print("STATS: ")
            score = self.evaluate(examples, current_cand)
            print("\t length: ", len(current_cand))
            print("\t Pool size: ", self._candidate_pool.qsize(), "\n")
            self.exp_count += 1
            self.max_queue_len = max(self.max_queue_len, self._candidate_pool.qsize())

            if self.exp_count == 101:
                self.stopped_early = True
                break
                
            if not current_cand.is_recursive():
                # expand the candidate and get possible expansions
                _ = hypothesis_space.expand(current_cand)
                exps = hypothesis_space.get_successors_of(current_cand)

                # Get scores for primitives using current candidate and each example
                primitives = self.get_best_primitives(examples, current_cand)
                exps = self.process_expansions(current_cand, examples, exps, primitives, hypothesis_space)

                # add into pool
                self.put_into_pool(exps)

                if self._candidate_pool.qsize() == 0:
                    self.stopped_early = True
                    break

        if self.stopped_early:
            return None

        self._solver.asserta(current_cand)
        return current_cand
                           father("e", "f"), father("f", "g"),
                           mother("h", "i"), mother("i", "j"))

    # positive examples
    pos = {grandparent("a", "c"), grandparent("e", "g"), grandparent("h", "j")}

    # negative examples
    neg = {grandparent("a", "b"), grandparent("a", "g"), grandparent("i", "j")}

    task = Task(positive_examples=pos, negative_examples=neg)

    # create Prolog instance
    prolog = SWIProlog()

    learner = SimpleBreadthFirstLearner(prolog, max_body_literals=3)

    # create the hypothesis space
    hs = TopDownHypothesisSpace(primitives=[
        lambda x: plain_extension(x, father, connected_clauses=True),
        lambda x: plain_extension(x, mother, connected_clauses=True)
    ],
                                head_constructor=grandparent,
                                expansion_hooks_reject=[
                                    lambda x, y: has_singleton_vars(x, y),
                                    lambda x, y: has_duplicated_literal(x, y)
                                ])

    program = learner.learn(task, background, hs)

    print(program)
예제 #10
0
    def top_down_plain(self):
        grandparent = c_pred("grandparent", 2)
        father = c_pred("father", 2)
        mother = c_pred("mother", 2)

        hs = TopDownHypothesisSpace(primitives=[
            lambda x: plain_extension(x, father),
            lambda x: plain_extension(x, mother)
        ],
                                    head_constructor=grandparent)

        current_cand = hs.get_current_candidate()
        assert len(current_cand) == 3

        expansions = hs.expand(current_cand[0])
        assert len(expansions) == 6

        expansions_2 = hs.expand(expansions[0])
        assert len(expansions_2) == 10

        expansions3 = hs.expand(expansions[1])
        assert len(expansions3) == 32

        hs.block(expansions[2])
        expansions4 = hs.expand(expansions[2])
        assert len(expansions4) == 0

        hs.remove(expansions[3])
        expansions5 = hs.get_successors_of(current_cand[0])
        assert len(expansions5) == 5

        hs.move_pointer_to(expansions[1])
        current_cand = hs.get_current_candidate()
        assert current_cand[0] == expansions[1]

        hs.ignore(expansions[4])
        hs.move_pointer_to(expansions[4])
        expansions6 = hs.get_current_candidate()
        assert len(expansions6) == 0
예제 #11
0
    prolog = SWIProlog()

    # create the hypothesis space
    hs = TopDownHypothesisSpace(primitives=[
        lambda x: plain_extension(x, not_space, connected_clauses=True),
        lambda x: plain_extension(x, mk_uppercase, connected_clauses=True),
        lambda x: plain_extension(x, mk_lowercase, connected_clauses=True),
        lambda x: plain_extension(x, is_empty, connected_clauses=True),
        lambda x: plain_extension(x, is_space, connected_clauses=True),
        lambda x: plain_extension(x, is_uppercase, connected_clauses=True),
        lambda x: plain_extension(x, not_uppercase, connected_clauses=True),
        lambda x: plain_extension(x, is_lowercase, connected_clauses=True),
        lambda x: plain_extension(x, not_lowercase, connected_clauses=True),
        lambda x: plain_extension(x, is_letter, connected_clauses=True),
        lambda x: plain_extension(x, not_letter, connected_clauses=True),
        lambda x: plain_extension(x, is_number, connected_clauses=True),
        lambda x: plain_extension(x, not_number, connected_clauses=True),
        lambda x: plain_extension(x, skip1, connected_clauses=True),
        lambda x: plain_extension(x, copy1, connected_clauses=True),
        lambda x: plain_extension(x, write1, connected_clauses=True),
        lambda x: plain_extension(x, copyskip1, connected_clauses=True)
    ],
                                head_constructor=b45,
                                expansion_hooks_reject=[
                                    lambda x, y: has_singleton_vars(x, y),
                                    lambda x, y: has_duplicated_literal(x, y)
                                ],
                                recursive_procedures=True)
    primitives = [
        b45(c_var('X')),
        b45(c_var('Y')),
예제 #12
0
    def process_expansions(self, current_cand: typing.Union[Clause, Procedure],
                           examples: Task, exps_raw: typing.Sequence[Clause],
                           primitives,
                           hypothesis_space: TopDownHypothesisSpace):
        # Encode current candidate to list
        encoded_current_cand = clause_to_list(current_cand,
                                              self.current_primitives.tolist())

        exps = []
        first = True
        for e in exps_raw:
            if isinstance(e, Recursion):
                if first:
                    # With the current hooks, only one recursive case is possible
                    exps.append(e.get_recursive_case()[0])
                    print("FOUND FOLLOWING RECURSIVE CASE AS EXTENSION: ")
                    print(e.get_recursive_case(), "\n")
                first = False
            else:
                exps.append(e)

        # eliminate every clause with more body literals than allowed
        exps = [cl for cl in exps if len(cl) <= self._max_body_literals]

        print("EXPANSIONS BEFORE FILTERING: ")
        self.exp_len.append(len(exps))
        print(exps, "\n")

        # check if every clause has solutions
        exps = [(cl, self._solver.has_solution(*cl.get_body().get_literals()))
                for cl in exps]
        new_exps = []

        for ind in range(len(exps)):
            if exps[ind][1]:
                current_exp = exps[ind][0]
                encoded_exp = clause_to_list(current_exp,
                                             self.current_primitives.tolist())
                prim_index = find_difference(encoded_current_cand, encoded_exp)
                if (not prim_index and self.rules != 0
                    ) or self.current_primitives[prim_index] in primitives:
                    # keep it if it has solutions and if it has an allowed primitive
                    pos, neg = self.evaluate_distinct(examples, current_exp)
                    new_exp = Triplet(current_exp, pos, neg)

                    if new_exp.func1() != new_exp.min_score:
                        new_exps.append(new_exp)

                    # TODO maybe at another place for better performance (currently not used)
                    self.set_example_weights(current_cand, current_exp,
                                             examples)
            else:
                # remove from hypothesis space if it does not
                hypothesis_space.remove(exps[ind][0])

        new_exps = sorted(new_exps,
                          key=cmp_to_key(Triplet.comparator),
                          reverse=True)[:self.filter_amount]
        new_exps_real = []

        for triplet in new_exps:
            new_exps_real.append(triplet.get_tuple())

        print("VIABLE EXTENSIONS: ")
        print(new_exps_real, "\n")
        return new_exps_real
예제 #13
0
    def _learn_one_clause(self, examples: Task,
                          hypothesis_space: TopDownHypothesisSpace) -> Clause:
        """
        Learns a single clause

        Returns a clause
        """
        # reset the search space
        hypothesis_space.reset_pointer()

        # empty the pool just in case
        self.initialise_pool()

        # put initial candidates into the pool
        self.put_into_pool(hypothesis_space.get_current_candidate())
        current_cand = None
        score = -100
        self._expansionOneClause = 0
        best = None

        while current_cand is None or (len(self._candidate_pool) >
                                       0) and self._expansionOneClause < 40000:
            # get first candidate from the pool
            current_cand = self.get_from_pool()
            print(self._expansion)

            # expand the candidate
            _ = hypothesis_space.expand(current_cand)
            # this is important: .expand() method returns candidates only the first time it is called;
            #     if the same node is expanded the second time, it returns the empty list
            #     it is safer than to use the .get_successors_of method
            exps = hypothesis_space.get_successors_of(current_cand)
            exps = [cl for cl in exps if len(cl) <= self._max_body_literals]

            new_exps = []
            # check if every clause has solutions
            for cl in exps:
                y = self.evaluate(task, cl)

                if y[0] > 0:
                    new_exps.append(cl)
                    if best == None:
                        best = (y[0], cl)
                    if (y[1] == 0):
                        self._expansion += 1
                        self._expansionOneClause += 1
                        self._result.append((self._expansion, y[1]))
                        return cl
                    self._expansion += 1
                    self._expansionOneClause += 1

                    self._result.append((self._expansion, y[0]))
                    if y[0] > best[0]:
                        best = (y[0], cl)
                    else:
                        if (y[0] == best[0]) & (len(cl.get_literals()) < len(
                                best[1].get_literals())):
                            best = (y[0], cl)
                else:
                    hypothesis_space.remove(cl)

            # add into pull
            self.put_into_pool(new_exps)

        print(best)
        return best[1]
예제 #14
0
    # # create the hypothesis space
    # hs = TopDownHypothesisSpace(primitives=[lambda x: plain_extension(x, father, connected_clauses=True),
    #                                         lambda x: plain_extension(x, mother, connected_clauses=True)],
    #                             head_constructor=grandparent,
    #                             expansion_hooks_reject=[lambda x, y: has_singleton_vars(x, y),
    #                                                     lambda x, y: has_duplicated_literal(x, y)])

    totalextension = []
    filtered_predicates = []

    for predicate in predicates:
        if predicate.name not in ["s", chosen_pred
                                  ] and predicate not in filtered_predicates:
            totalextension.append(
                lambda x, predicate=predicate: plain_extension(
                    x, predicate, connected_clauses=True))
            filtered_predicates.append(predicate)

    # create the hypothesis space
    hs = TopDownHypothesisSpace(primitives=totalextension,
                                head_constructor=c_pred("train_task", 1),
                                expansion_hooks_reject=[
                                    lambda x, y: has_singleton_vars(x, y),
                                    lambda x, y: has_duplicated_literal(x, y)
                                ])

    program = learner.learn(task, background, hs)

    print(program)