예제 #1
0
    def has_solution(self, *query: Union[Atom, Not]):
        var_store = {}

        if len(query) == 1:
            query = query[0]
            predicate_name = query.get_predicate().get_name()
            query_args = swipy.swipy_new_term_refs(query.get_predicate().get_arity())

            for ind, arg in enumerate(query.get_arguments()):
                _to_swipy_ref(arg, query_args + ind, var_store)

            pred = swipy.swipy_predicate(predicate_name, query.get_predicate().get_arity(), None)
            query = swipy.swipy_open_query(pred, query_args)
            r = swipy.swipy_next_solution(query)
            swipy.swipy_close_query(query)

            return True if r else False
        else:
            swipy_objs = [_lit_to_swipy(x, var_store) if isinstance(x, Atom) else _neg_to_swipy(x, var_store) for x
                          in query]
            first = swipy_objs[0]
            rest = _conjoin_literals(swipy_objs[1:])

            compound_arg = swipy.swipy_new_term_refs(2)
            swipy.swipy_put_term(compound_arg, first)
            swipy.swipy_put_term(compound_arg + 1, rest)

            predicate = swipy.swipy_predicate(",", 2, None)
            query = swipy.swipy_open_query(predicate, compound_arg)
            r = swipy.swipy_next_solution(query)
            swipy.swipy_close_query(query)

            return True if r else False
예제 #2
0
파일: SWIProlog.py 프로젝트: hayesall/pylo2
def _var_to_swipy_ref(var: Variable, swipy_ref, lit_var_store: Dict[Variable,
                                                                    int]):
    if var in lit_var_store:
        swipy.swipy_put_term(swipy_ref, lit_var_store[var])
    else:
        swipy.swipy_put_variable(swipy_ref)
        lit_var_store[var] = swipy_ref
예제 #3
0
    def query(self, *query, **kwargs):
        if 'max_solutions' in kwargs:
            max_solutions = kwargs['max_solutions']
        else:
            max_solutions = -1

        vars_of_interest = [[y for y in x.get_arguments() if isinstance(y, Variable)] for x in query]
        vars_of_interest = reduce(lambda x, y: x + y, vars_of_interest, [])
        vars_of_interest = reduce(lambda x, y: x + [y] if y not in x else x, vars_of_interest, [])
        var_store = {}
        for v in vars_of_interest:
            tmp_v = swipy.swipy_new_term_ref()
            swipy.swipy_put_variable(tmp_v)
            var_store[v] = tmp_v

        if len(query) == 1:
            query = query[0]
            predicate_name = query.get_predicate().get_name()
            query_args = swipy.swipy_new_term_refs(query.get_predicate().get_arity())

            for ind, arg in enumerate(query.get_arguments()):
                _to_swipy_ref(arg, query_args + ind, var_store)

            pred = swipy.swipy_predicate(predicate_name, query.get_predicate().get_arity(), None)
            query = swipy.swipy_open_query(pred, query_args)
        else:
            swipy_objs = [_lit_to_swipy(x, var_store) if isinstance(x, Atom) else _neg_to_swipy(x, var_store) for x
                          in query]
            first = swipy_objs[0]
            rest = _conjoin_literals(swipy_objs[1:])

            compound_arg = swipy.swipy_new_term_refs(2)
            swipy.swipy_put_term(compound_arg, first)
            swipy.swipy_put_term(compound_arg + 1, rest)

            predicate = swipy.swipy_predicate(",", 2, None)
            query = swipy.swipy_open_query(predicate, compound_arg)

        r = swipy.swipy_next_solution(query)

        all_solutions = []
        var_index_var = dict([(var_store[v], v) for v in var_store])

        while r and max_solutions != 0:
            max_solutions -= 1

            tmp_solution = {}
            for var in var_store:
                tmp_solution[var] = _read_swipy(var_store[var], swipy_term_to_var=var_index_var)

            all_solutions.append(tmp_solution)
            r = swipy.swipy_next_solution(query)

        swipy.swipy_close_query(query)

        return all_solutions
예제 #4
0
def _conjoin_literals(lits: Sequence[int]):
    if len(lits) == 1:
        return lits[0]
    else:
        f_atm = swipy.swipy_new_atom(",")
        conj_functor = swipy.swipy_new_functor(f_atm, 2)

        compound_arg = swipy.swipy_new_term_refs(2)
        conj = swipy.swipy_new_term_ref()
        swipy.swipy_put_term(compound_arg, lits[0])
        swipy.swipy_put_term(compound_arg + 1, _conjoin_literals(lits[1:]))
        swipy.swipy_cons_functor(conj, conj_functor, compound_arg)

        return conj
예제 #5
0
    def _wrap_in_call_time(self, query, time):
        """
        Wraps the query in call_with_time_limit. Assumes that query is already translated to swipy
        :param query:
        :param time:
        :return:
        """
        func_atm = swipy.swipy_new_atom("call_with_time_limit")
        func = swipy.swipy_new_functor(func_atm, 2)

        compound_arg = swipy.swipy_new_term_refs(2)
        _num_to_swipy_ref(time, compound_arg)
        swipy.swipy_put_term(compound_arg + 1, query)

        final_term = swipy.swipy_new_term_ref()
        swipy.swipy_cons_functor(final_term, func, compound_arg)

        return final_term
예제 #6
0
def _cl_to_swipy(clause: Clause, lit_var_store: Dict[Variable, int]):
    body: typing.Sequence[Union[Atom, Not]] = clause.get_body().get_literals()
    head: Atom = clause.get_head()

    body: typing.List[int] = [_lit_to_swipy(x, lit_var_store)
                              if isinstance(x, Atom)
                              else _neg_to_swipy(x, lit_var_store)
                              for x in body]

    head = _lit_to_swipy(head, lit_var_store)
    body = _conjoin_literals(body)

    clause_atom = swipy.swipy_new_atom(":-")
    clause_functor = swipy.swipy_new_functor(clause_atom, 2)

    entire_clause = swipy.swipy_new_term_ref()
    compound_arg = swipy.swipy_new_term_refs(2)
    swipy.swipy_put_term(compound_arg, head)
    swipy.swipy_put_term(compound_arg + 1, body)
    swipy.swipy_cons_functor(entire_clause, clause_functor, compound_arg)

    return entire_clause
예제 #7
0
    def _prepare_query(self, var_store, *query, max_time=None, max_depth=None, max_inference=None):
        """
        Prepares the query

        Return swipl-transformed predicate and arguments needed to posed the query to the engine

        :param var_store:
        :param query:
        :param max_time:
        :param max_depth:
        :param max_inference:
        :return:
        """
        if len(query) == 1:
            query = query[0]

            if not (max_time or max_depth or max_inference):
                predicate_name = query.get_predicate().get_name()
                query_args = swipy.swipy_new_term_refs(query.get_predicate().get_arity())

                for ind, arg in enumerate(query.get_arguments()):
                    _to_swipy_ref(arg, query_args + ind, var_store)

                pred = swipy.swipy_predicate(predicate_name, query.get_predicate().get_arity(), None)

                return pred, query_args
            else:
                query_term = _lit_to_swipy(query, var_store)

                if max_time:
                    # if time limit should be imposed on the query

                    pred = swipy.swipy_predicate("call_with_time_limit", 2, None)
                    query_args = swipy.swipy_new_term_refs(2)

                    swipy.swipy_put_integer(query_args, max_time)
                    swipy.swipy_put_term(query_args+1, query_term)

                    return pred, query_args
                elif max_depth or max_inference:
                    pred = swipy.swipy_predicate("call_with_depth_limit", 3, None) if max_depth else swipy.swipy_predicate("call_with_inference_limit", 3, None)
                    query_args = swipy.swipy_new_term_refs(3)
                    swipy.swipy_put_term(query_args, query_term)

                    if max_depth:
                        _num_to_swipy_ref(max_depth, query_args + 1)
                    else:
                        _num_to_swipy_ref(max_inference, query_args + 1)
                    swipy.swipy_put_variable(query_args + 2)

                    return pred, query_args

        else:
            swipy_objs = [_lit_to_swipy(x, var_store) if isinstance(x, Atom) else _neg_to_swipy(x, var_store) for x
                          in query]

            if not (max_time or max_depth or max_inference):
                first = swipy_objs[0]
                rest = _conjoin_literals(swipy_objs[1:])

                compound_arg = swipy.swipy_new_term_refs(2)
                swipy.swipy_put_term(compound_arg, first)
                swipy.swipy_put_term(compound_arg + 1, rest)

                predicate = swipy.swipy_predicate(",", 2, None)

                return predicate, compound_arg
            else:
                query_term = _conjoin_literals(swipy_objs)

                if max_time:
                    # if time limit should be imposed on the query
                    wrapped_term = self._wrap_in_call_time(query_term, max_time)
                    exception = swipy.swipy_new_atom('time_limit_exceeded')
                    fail = swipy.swipy_new_atom('fail')

                    pred = swipy.swipy_predicate("catch", 3, None)
                    query_args = swipy.swipy_new_term_refs(3)
                    swipy.swipy_put_term(query_args, wrapped_term)
                    swipy.swipy_put_term(query_args + 1, exception)
                    swipy.swipy_put_term(query_args + 2, fail)

                    return pred, query_args
                elif max_depth or max_inference:
                    pred = swipy.swipy_predicate("call_with_depth_limit", 3, None) if max_depth else swipy.swipy_predicate("call_with_inference_limit", 3, None)
                    query_args = swipy.swipy_new_term_refs(3)
                    swipy.swipy_put_term(query_args, query_term)

                    if max_depth:
                        _num_to_swipy_ref(max_depth, query_args + 1)
                    else:
                        _num_to_swipy_ref(max_inference, query_args + 1)
                    swipy.swipy_put_variable(query_args + 2)

                    return pred, query_args