Пример #1
0
def max_var_occurrences(head: Atom, body: Body, max_occurrence: int) -> bool:
    """
    Returns True if the predicate pred does not appear more than max_occurrence times in the clause
    """
    if len(body.get_variables()) > 0:
        counter = Counter(body.get_variables())
        if (body.get_literals()[-1].get_predicate().get_name() == 'copy1'):
            print(counter)

        return counter.most_common()[0][1] >= max_occurrence
    else:
        return False
Пример #2
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
Пример #3
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
Пример #4
0
    def initialise(self, initial_clause: typing.Union[Clause, Body]) -> None:
        """
        Initialises the search space. It is possible to provide an initial
        clause to initialize the hypothesis space with (instead of :-). 
        """
        if isinstance(self._head_constructor, (Predicate, FillerPredicate)):
            if isinstance(self._head_constructor, Predicate):
                # create possible heads
                head_variables = [chr(x) for x in range(ord("A"), ord("Z"))
                                  ][:self._head_constructor.get_arity()]

                possible_heads = [
                    self._head_constructor(*list(x))
                    for x in combinations_with_replacement(
                        head_variables, self._head_constructor.get_arity())
                ]
            else:
                possible_heads = self._head_constructor.all_possible_atoms()

            # create empty clause or use initial clause
            if initial_clause:
                clause = initial_clause if isinstance(
                    initial_clause, Body) else initial_clause.get_body()
            else:
                clause = Body()
            if len(clause.get_literals()) > 0 and len(clause.get_variables(
            )) < self._head_constructor.get_arity():
                raise AssertionError(
                    "Cannot provide an initial clause with fewer distinct variables than the head predicate!"
                )

            init_head_dict = {
                "ignored": False,
                "blocked": False,
                "visited": False
            }
            self._hypothesis_space.add_node(clause)
            self._hypothesis_space.nodes[clause]["heads"] = dict([
                (x, init_head_dict.copy()) for x in possible_heads
            ])
            self._hypothesis_space.nodes[clause]["visited"] = False

            self._pointers["main"] = clause
            self._root_node = clause
        else:
            raise Exception(
                f"Unknown head constructor ({self._head_constructor}")
Пример #5
0
    def _add_to_body_fixed_arity(self, body: Body,
                                 arity: int) -> Sequence[Body]:
        new_pred_stash = {}  # arg_types tuple -> pred

        vars = body.get_variables()

        bodies = []

        args = list(combinations(vars, arity))
        for ind in range(len(args)):
            arg_types = (x.get_type() for x in args[ind])

            if arg_types in new_pred_stash:
                pred = new_pred_stash[arg_types]
            else:
                self._instance_counter += 1
                pred = c_pred(f"{self._prefix_name}{self._instance_counter}",
                              arity, arg_types)
                new_pred_stash[arg_types] = pred

            bodies.append(body + pred(*args[ind]))

        return bodies
Пример #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