Пример #1
0
def endless_recursion_exists(head: Atom, body: Body) -> bool:
    for literal in body.get_literals():
        if head.get_predicate() == literal.get_predicate():
            if literal.get_variables()[0] == head.get_variables()[0]:
                return True
            return False

    return False
Пример #2
0
def get_recursive_calls_amount(head: Atom, body: Body) -> int:
    rec_count = 0
    for predicate in _get_body_predicates_list(body):
        if head.get_predicate() == predicate:
            rec_count += 1

    return rec_count
Пример #3
0
def max_var(head: Atom, body: Body, max_count: int) -> bool:
    """
    Return True if there are no more than max_count variables in the clause
    """
    vars = body.get_variables()
    for v in head.get_variables():
        if v not in vars:
            vars += [v]
    return True if len(vars) <= max_count else False
Пример #4
0
 def all_possible_atoms(self) -> Sequence[Atom]:
     """
     Creates all possible argument configurations for the atom
     """
     head_variables = [c_var(chr(x))
                       for x in range(ord("A"), ord("Z"))][:self._arity]
     if self._arity is not None:
         return [
             Atom(self.new(), list(x))
             for x in product(head_variables, repeat=self._arity)
         ]
     else:
         combos = []
         for i in range(self._min_arity, self._max_arity):
             combos += [
                 Atom(self.new(arity=i), list(x))
                 for x in product(head_variables, repeat=i)
             ]
         return combos
Пример #5
0
    def _from_body_fixed_arity(
        self,
        body: Body,
        arity: int = None,
        arg_types: Sequence[Type] = None,
        use_as_head_predicate: Predicate = None,
    ) -> Sequence[Atom]:
        """
        Creates a head atom given the body of the clause
        :param body:
        :param arity: (optional) desired arity if specified with min/max when constructing the FillerPredicate
        :param arg_types: (optional) argument types to use
        :return:
        """
        assert bool(arity) != bool(arg_types)
        vars = body.get_variables()

        if use_as_head_predicate and arg_types is None:
            arg_types = use_as_head_predicate.get_arg_types()

        if arg_types is None:
            base = [vars] * arity
        else:
            matches = {}

            for t_ind in range(len(arg_types)):
                matches[t_ind] = []
                for v_ind in range(len(vars)):
                    if vars[v_ind].get_type() == arg_types[t_ind]:
                        matches[t_ind].append(vars[v_ind])

            base = [matches[x] for x in range(arity)]

        heads = []
        for comb in product(*base):
            self._instance_counter += 1
            if use_as_head_predicate is not None:
                pred = use_as_head_predicate
            elif arg_types is None:
                pred = c_pred(f"{self._prefix_name}_{self._instance_counter}",
                              arity)
            else:
                pred = c_pred(
                    f"{self._prefix_name}_{self._instance_counter}",
                    len(arg_types),
                    arg_types,
                )

            heads.append(Atom(pred, list(comb)))

        return heads
Пример #6
0
    def _create_possible_heads(
            self,
            body: Body,
            use_as_head_predicate: Predicate = None) -> typing.Sequence[Atom]:
        """
        Creates possible heads for a given body

        if the _head_constructor is Predicate, it makes all possible combinations that matches the types in the head
        """
        vars = body.get_variables()

        if isinstance(self._head_constructor, Predicate):
            arg_types = self._head_constructor.get_arg_types()

            # matches_vars = []
            # for i in range(len(arg_types)):
            #     matches_vars[i] = []
            #     for var_ind in range(len(vars)):
            #         if arg_types[i] == vars[var_ind].get_type():
            #             matches_vars[i].append(vars[var_ind])
            #
            # bases = [matches_vars[x] for x in range(self._head_constructor.get_arity())]
            # heads = []
            #
            # for comb in product(*bases):
            #     heads.append(Atom(self._head_constructor, list(comb)))
            heads = []
            for comb in combinations(vars, self._head_constructor.get_arity()):
                if [x.get_type() for x in comb] == arg_types:
                    heads.append(Atom(self._head_constructor, list(comb)))
            return heads
        elif isinstance(self._head_constructor, FillerPredicate):
            return self._head_constructor.new_from_body(
                body, use_as_head_predicate=use_as_head_predicate)
        else:
            raise Exception(
                f"Unknown head constructor {self._head_constructor}")
Пример #7
0
def has_singleton_vars(head: Atom, body: Body) -> bool:
    """
    Returns True is the clause has a singleton variable (appears only once)
    """
    if len(body) == 0:
        return False

    vars = {}
    head_vars = head.get_variables()
    for ind in range(len(head_vars)):
        if head_vars[ind] not in vars:
            vars[head_vars[ind]] = head_vars.count(head_vars[ind])

    bvars = body.get_variables()
    body_vars_flat = reduce(lambda x, y: x + y,
                            [x.get_variables() for x in body.get_literals()],
                            [])
    for ind in range(len(bvars)):
        if bvars[ind] in vars:
            vars[bvars[ind]] += body_vars_flat.count(bvars[ind])
        else:
            vars[bvars[ind]] = body_vars_flat.count(bvars[ind])

    return True if any([k for k, v in vars.items() if v == 1]) else False
Пример #8
0
def head_first(head: Atom, body: Body) -> bool:
    return len(
        set(body.get_literals()[0].get_variables()).intersection(
            set(head.get_variables()))) != 0
Пример #9
0
 # define the Variables
 H = c_var("H")
 Ta = c_var("Ta")
 Tb = c_var("Tb")
 A = c_var("A")
 B = c_var("B")
 C = c_var("C")
 D = c_var("D")
 E = c_var("E")
 H1 = c_var("H1")
 H2 = c_var("H2")
 Z = c_var("Z")
 O = c_var("O")
 N = c_var("N")
 # create clauses
 head = Atom(not_space, [A])
 body = Atom(is_space, [A])
 clause1 = Clause(head, Body(Not(body)))
 head = Atom(is_uppercase, [Structure(s, [Pair(H, Z), O])])
 body = Atom(is_uppercase_aux, [H])
 clause2 = Clause(head, Body(body))
 head = Atom(not_uppercase, [A])
 body = Atom(is_uppercase, [A])
 clause3 = Clause(head, Body(Not(body)))
 head = Atom(is_lowercase, [Structure(s, [Pair(H, Z), O])])
 body = Atom(is_lowercase_aux, [H])
 clause4 = Clause(head, Body(body))
 head = Atom(not_lowercase, [A])
 body = Atom(is_lowercase, [A])
 clause5 = Clause(head, Body(Not(body)))
 head = Atom(is_letter, [Structure(s, [Pair(H, Z), O])])
Пример #10
0
    def _get_recursions(self, node: Body) -> typing.Sequence[Recursion]:
        """
        Prepares the valid recursions
        """
        pointer_name = self._hypothesis_space.nodes[node]["partner"]
        init_pointer_value = self._pointers[pointer_name]
        last_pointer_value = None

        valid_heads = list(self._hypothesis_space.nodes[node]["heads"].keys())
        recursions = []

        # for each valid head
        for h_ind in range(len(valid_heads)):
            c_head: Atom = valid_heads[h_ind]
            recursive_clause = Clause(c_head, node)

            frontier = [self._pointers[pointer_name]]

            while len(frontier) > 0:
                focus_node = frontier[0]
                frontier = frontier[1:]

                # find matching heads
                focus_node_heads: typing.Sequence[Atom] = list(
                    self._hypothesis_space.nodes[focus_node]["heads"].keys())
                focus_node_heads = [
                    x for x in focus_node_heads
                    if x.get_predicate().get_arg_types() ==
                    c_head.get_predicate().get_arg_types()
                ]

                # prepare recursion
                for bcl_ind in range(len(focus_node_heads)):
                    if isinstance(self._head_constructor, Predicate):
                        recursions.append(
                            Recursion([
                                Clause(focus_node_heads[bcl_ind], focus_node),
                                recursive_clause,
                            ]))
                    else:
                        # if the filler predicate is used to construct heads, make sure the same head predicate is used
                        head_args = focus_node_heads[bcl_ind].get_arguments()
                        recursions.append(
                            Recursion([
                                Clause(
                                    Atom(c_head.get_predicate(), head_args),
                                    focus_node,
                                ),
                                recursive_clause,
                            ]))

                # extend the frontier - exclude recursive nodes
                to_add = [
                    x for x in self._hypothesis_space.successors(focus_node)
                    if "partner" not in self._hypothesis_space.nodes[x]
                ]
                frontier += to_add
                last_pointer_value = focus_node

            # reset the pointer value for next valid head
            self.reset_pointer(pointer_name, init_pointer_value)

        # set the pointer to the last explored clause
        self.reset_pointer(pointer_name, last_pointer_value)

        return recursions
Пример #11
0
 # define the Variables
 H = c_var("H")
 Ta = c_var("Ta")
 Tb = c_var("Tb")
 A = c_var("A")
 B = c_var("B")
 C = c_var("C")
 D = c_var("D")
 E = c_var("E")
 H1 = c_var("H1")
 H2 = c_var("H2")
 Z = c_var("Z")
 O = c_var("O")
 N = c_var("N")
 # create clauses
 head = Atom(not_space, [A])
 body = Atom(is_space, [A])
 clause1 = Clause(head, Body(Not(body)))
 head = Atom(is_uppercase, [Structure(s, [Pair(H, Z), O])])
 body = Atom(is_uppercase_aux, [H])
 clause2 = Clause(head, Body(body))
 head = Atom(not_uppercase, [A])
 body = Atom(is_uppercase, [A])
 clause3 = Clause(head, Body(Not(body)))
 head = Atom(is_lowercase, [Structure(s, [Pair(H, Z), O])])
 body = Atom(is_lowercase_aux, [H])
 clause4 = Clause(head, Body(body))
 head = Atom(not_lowercase, [A])
 body = Atom(is_lowercase, [A])
 clause5 = Clause(head, Body(Not(body)))
 head = Atom(is_letter, [Structure(s, [Pair(H, Z), O])])