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
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
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
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
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
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
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