Найти все решения для предиката - PullRequest
5 голосов
/ 20 июля 2011

Я пытаюсь определить предикат, который получает один термин со свободными переменными и возвращает список сопоставлений этих переменных, поэтому, например, если база данных имеет значение

a(0,1).
a(1,1).

, ожидаемый результат будет

?- eval(a(X,1),Maps).
Maps = [[[X,0]],[[X,1]]].
?- eval(a(X,Y),Maps).
Maps = [[[X,0],[Y,1]],[[X,1],[Y,1]]].

Я пытался сделать это с помощью findall/3, но я не могу найти способ запросить свободные переменные и их возможные значения.Если это поможет, я использую swiprolog.Спасибо.

Ответы [ 3 ]

3 голосов
/ 20 июля 2011

Вот решение похожей проблемы. Вместо списка ответов, представленного в виде списка с записями [V,term] для каждой переменной, запрос goal_answers(Goal, Answerp) находит пару Vars-Terms.

goal_answerp(Goal, Answerp) :-
   term_variables(Goal, Vars),
   findall(Vars, Goal, Substs),
   Answerp = Vars-Substs.

?- goal_answerp(a(X,1), Ms).
Ms = [X]-[[0],[1]].

?- goal_answerp(a(X,Y), Ms).
Ms = [X,Y]-[[0,1],[1,1]].

[Редактировать] Чтобы получить ответы в исходном формате, используйте library(lambda):

?- goal_answerp(a(X,1), Vs-Dss),
      maplist(Vs+\Ds^VDs^maplist(\V^D^[V,D]^true,Vs,Ds,VDs),Dss,VDss).
Vs = [X],
Dss = [[0],[1]],
VDss = [[[X,0]],[[X,1]]].

?- goal_answerp(a(X,Y), Vs-Dss),
      maplist(Vs+\Ds^VDs^maplist(\V^D^[V,D]^true,Vs,Ds,VDs),Dss,VDss).
Vs = [X,Y],
Dss = [[0,1],[1,1]],
VDss = [[[X,0],[Y,1]],[[X,1],[Y,1]]].
2 голосов
/ 20 июля 2011

Существует проблема с тем, что вы хотите сделать.Удобное для пользователя имя, которое вы даете переменным (например, X, Y), известно синтаксическому анализатору верхнего уровня, но «потеряно» внутри вашей программы.В этом фрагменте будут перечислены все привязки, но переменные будут иметь общие имена:

find_mappings(Template, Mappings):-
  term_variables(Template, Vars),
  find_mappings1(Vars, Mapping),
  findall(Mapping, Template, Mappings).

find_mappings1([], []).
find_mappings1([Var|Vars], [[Name,Var]|Mappings]):-
  term_to_atom(Var, Name),
  find_mappings1(Vars, Mappings).

?- find_mappings(a(X,Y), L).
L = [[['_G385', 0], ['_G386', 1]], [['_G385', 1], ['_G386', 1]]].

Вы можете предпочесть добавить еще один аргумент в вашу процедуру, чтобы получить правильные имена ваших переменных:

find_mappings(Template, Names, Mappings):-
  term_variables(Template, Vars),
  find_mappings1(Vars, Names, Mapping),
  findall(Mapping, Template, Mappings).

find_mappings1([], [], []).
find_mappings1([Var|Vars], [Name|Names], [[Name,Var]|Mappings]):-
  find_mappings1(Vars, Names, Mappings).

?- find_mappings(a(X,Y), ['X', 'Y'], L).
L = [[['X', 0], ['Y', 1]], [['X', 1], ['Y', 1]]].
0 голосов
/ 20 июля 2011

Передо мной нет переводчика, но я думаю, что вы могли бы сделать это для этой конкретной установки с помощью предиката 'a'.

var(X), 
var(Y), 
findall(U, 
  ( a(XSol,YSol), U=[[X,XSol], [Y,YSol]] ), 
  Maps).

(вар может быть ненужным) Я не знаю, почему вы хотели бы использовать этот подход к любой проблеме, хотя ...

Проверьте unifiable / 3 для потенциально лучшего способа сделать что-то подобное.

...