Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: ailnlvОтветов: 3

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

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

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

prologprolog-findall

Ответы

Ответ 1 · рейтинг 3 · false

Вот решение похожей проблемы. Вместо списка ответов, представленного в виде списка с записями [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 · рейтинг 2 · gusbro

Есть проблема с тем, что вы хотите сделать. Удобное для пользователя имя, которое вы даете переменным (например, 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]]].

Ответ 3 · DaveEdelstein

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

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

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы