Нужна помощь в понимании Пролога добавить / 3 и обратного / 2 и вывод трассировки - PullRequest
0 голосов
/ 17 декабря 2018

Это вопрос

enter image description here

найти значение А.


inverse([],[]).

inverse([H|T],D) :-
  inverse(T,Z),
  append(Z,[H],D).

append([],X,X).

append([X|L],M,[X|N]) :-
  append(L,M,N).

Этоответ:

enter image description here

Пожалуйста, помогите мне понять это!

1 Ответ

0 голосов
/ 17 декабря 2018

Изображения кода Пролога, которые вы разместили, показывают какой-то необычный или очень старый Пролог, в частности, для списка использование [H:T] теперь выполняется как [H|T], обратите внимание на изменение с : на |, и<= чаще встречается как :-.

Чтобы понять код Пролога, легче начать снизу вверх.Я не буду описывать унификацию или обратную цепочку , поскольку для перехода на этот уровень детализации здесь потребуются главы, стоящие здесь.

Первый предикат, который нужно понять, это Append / 3 .Обычно вы никогда не видите код для добавления, указанный как встроенный предикат, но здесь он предоставляется.

Append / 3 имеет три параметра, которые являются списком.Первые два добавляются вместе, чтобы сформировать третий.

?- append_01([],[],R).
R = [].

?- append_01([a],[],R).
R = [a].

?- append_01([],[a],R).
R = [a].

?- append_01([a],[b],R).
R = [a, b].

, но предикаты Prolog могут иметь другие операции режимов , которые могут привязывать значения к тому, что будет считаться входными параметрами в других языках программирования.Например,

?- append(X,[b],[a,b]).
X = [a] ;
false.

?- append_01([a],Y,[a,b]).
Y = [b].

?- append(X,Y,[a,b]).
X = []    , Y = [a, b] ;
X = [a]   , Y = [b]    ;
X = [a, b], Y = []     ;
false.

или может быть просто использован для проверки аргументов

?- append([a],[b],[a,b]).
true.

?- append([a],[c],[a,b]).
false.

Далее следует предикат обратный / 2, который в Прологе более известен как reverse / 2, и снова здесь приводится исходный код.

Это просто берет один список и переворачивает его, например,

?- inverse([],X).
X = [].

?- inverse([a],X).
X = [a].

?- inverse([a,b],X).
X = [b, a].

, однако эта версия исходного кода не очень хорошо работает вдругие режимы, например

?- inverse(X,[]).
X = [] ;

Action (h for help) ? abort
% Execution Aborted

, но это не имеет значения, чтобы ответить на вопрос.


Следующая часть того, что вы опубликовали, - это след выполнения запроса

?- inverse([[1,2,3],[5,4]],A).

Чтобы использовать трассировку в вашем коде, так как есть встроенный предикат для append / 3, мне пришлось переименовать предикат.Вот код, который я использовал.

inverse([],[]).

inverse([H|T],D) :-
  inverse(T,Z),
  append_01(Z,[H],D).

append_01([],X,X).

append_01([X|L],M,[X|N]) :-
  append_01(L,M,N).

Использование SWI-Prolog

настройка трассы

?- visible(+all),leash(-all). 

запуск трассировки

trace.

выполнить запрос

[trace] ?- inverse([[1,2,3],[5,4]],A).

возвращает

   Call: (8) inverse([[1, 2, 3], [5, 4]], _7548)
   Unify: (8) inverse([[1, 2, 3], [5, 4]], _7548)
   Call: (9) inverse([[5, 4]], _7794)
   Unify: (9) inverse([[5, 4]], _7794)
   Call: (10) inverse([], _7794)
   Unify: (10) inverse([], [])
   Exit: (10) inverse([], [])
   Call: (10) append_01([], [[5, 4]], _7802)
   Unify: (10) append_01([], [[5, 4]], [[5, 4]])
   Exit: (10) append_01([], [[5, 4]], [[5, 4]])
   Exit: (9) inverse([[5, 4]], [[5, 4]])
   Call: (9) append_01([[5, 4]], [[1, 2, 3]], _7548)
   Unify: (9) append_01([[5, 4]], [[1, 2, 3]], [[5, 4]|_7792])
   Call: (10) append_01([], [[1, 2, 3]], _7792)
   Unify: (10) append_01([], [[1, 2, 3]], [[1, 2, 3]])
   Exit: (10) append_01([], [[1, 2, 3]], [[1, 2, 3]])
   Exit: (9) append_01([[5, 4]], [[1, 2, 3]], [[5, 4], [1, 2, 3]])
   Exit: (8) inverse([[1, 2, 3], [5, 4]], [[5, 4], [1, 2, 3]])
A = [[5, 4], [1, 2, 3]].

Я не буду объяснять детали трассировки, поскольку другие SO Q & A делают , что .


Трасса, которую вы опубликовали, также содержит больше деталей, чем сгенерированная с помощью trace, например, привязок (θ).

Чтобы увидеть привязки, используйте gtrace /0

?- gtrace.
% The graphical front-end will be used for subsequent tracing
true.

, затем выполните запрос

[trace]?- inverse([[1,2,3],[5,4]],A).

и нажмите пробел, чтобы перейти на один шаг.Вам придется экспериментировать с ним, чтобы узнать, как он работает;AFAIK нет опубликованной документации о том, как его использовать.

enter image description here


Из комментария OP:

Есть некоторые замены букв и цифр и тета-символа, которые делаютМне трудно понять.

Хотя привязки (θ) более специфичны для логических языков , числа также встречаются в стековых функциональных языках ,см. индекс Де Брюина .Кроме того, вместо написания привязок с использованием вертикального разделителя строк (---), я предпочитаю использовать (as), как показано здесь .

Строки 1 -4 являются только указанным исходным кодомснова.

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

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

На что вы отметили в комментариях Res(_,_) относится к предыдущим строкам трассировки.Таким образом, Res (5,2) в строке 6 можно прочитать, так как строка 6 является результатом вызова из строки 5 и затем вызывает строку 2.

Унификации или привязки (θ) отображаются как наборы,Я не совсем уверен, что представляют номера супер и субскриптов, но они явно связаны с индексами Де Брюина.Вам нужно будет попросить своего учителя объяснить супер и вспомогательные сценарии.

После нескольких попыток объяснить это только текстом, я, наконец, прибег к использованию Microsoft Visio, чтобы сделать это в виде графического дерева, которое было намного проще, быстрее и точнее.

Даже если это не было нужно, я добавиллиния трассировки выводится из SWI-Prolog в изображение, а затем помещает только строки вызова в соответствующие места в дереве, так что если вы хотите соотнести их, вы можете.Я сделал это для себя, чтобы проверить, правильно ли это.

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

enter image description here

...