Найти все решения предиката

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

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. Спасибо.


person ailnlv    schedule 20.07.2011    source источник
comment
Согласно фактам в вашей БД, я думаю, что второй пример должен быть Maps = [[[X,0], [Y,1]], [[X,1], [Y,1]]]   -  person gusbro    schedule 20.07.2011
comment
Вы правы, я исправлю это прямо сейчас. Извините, я мало спал, пытаясь решить эту проблему.   -  person ailnlv    schedule 20.07.2011


Ответы (3)


Вот решение похожей проблемы. Вместо списка ответов, представленного в виде списка с записями [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]]].
person false    schedule 20.07.2011
comment
Спасибо, это работает, но вы должны заменить строку, которая говорит Answerp = Vars-Substs. на Pair = Vars-Substs. - person ailnlv; 20.07.2011
comment
Спасибо - так бывает, когда думаешь, пока печатаешь. @gusbro: Answers был бы списком, но это пара. - person false; 20.07.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]]].
person gusbro    schedule 20.07.2011

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

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

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

Ознакомьтесь с unified/3, чтобы узнать о потенциально лучшем способе сделать что-то. как это.

person DaveEdelstein    schedule 20.07.2011
comment
Я не знаю, действительно ли это необходимо, но мне нужно выполнять внутреннее и левое соединения наборов сопоставлений (в основном я разбираю шаблоны SPARQL, но с произвольными предложениями вместо троек и использую только и и opt). Это решение почти работает, но имеет проблему, описанную gusbro, заключающуюся в отсутствии исходных имен переменных. Он также должен работать с произвольными предложениями, а не только с бинарными предложениями с известным именем. Спасибо. - person ailnlv; 20.07.2011