Нужна помощь в понимании Prolog append / 3 и inverse / 2 и вывода трассировки

Это вопрос

Нужна помощь в понимании Prolog append / 3 и inverse / 2 и вывода трассировки

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


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

Вот ответ:

Нужна помощь в понимании Prolog append / 3 и inverse / 2 и вывода трассировки

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

Вы понимаете, как работает унификация?

Guy Coder 17.12.2018 16:29

Извини, в следующий раз буду осторожен.

Mai Hoàng Nam 17.12.2018 16:53

Я не знаю, как перевести изображение в код.

Mai Hoàng Nam 17.12.2018 16:55

Просто я впервые делаю упражнение по прологу, и я не знал, с чего начать.

Mai Hoàng Nam 17.12.2018 16:56
I don't know how to translate an image to code. Не беспокойся об этом. Вы новичок в Prolog и новичок в StackOverflow, и, как я отметил в своем ответе, исходный код у вас нестандартный.
Guy Coder 17.12.2018 16:57

Пожалуйста, проверьте "Какой сайт?" на предмет общих проблем. Stack Overflow - это не учебник или справочный сайт.

Prune 17.12.2018 22:57

@Prune Вопрос действительно не по теме для вопроса Prolog здесь. Что делает это сложнее, чем большинство, так это то, что, как отмечает ОП, профессор старый, и это ясно видно в примере кода. Я видел подобное Прологу только в 70-х и 80-х годах или в книгах, сочетающих математику и логику. Я не использую форматирование трассировки.

Guy Coder 17.12.2018 23:36

Я не знаю, как перевести изображение в код. Хорошо, хорошо, я знаю, что мне не следует задавать себе вопросы в StackOverflow, я больше не буду этого делать. Guy Coder, вы очень мне помогаете, но я думаю, что мы не должны заканчивать эту тему здесь для сообщества.

Mai Hoàng Nam 18.12.2018 03:08

«Stack Overflow - это не учебник или справочный сайт». Мне очень жаль.

Mai Hoàng Nam 18.12.2018 03:08

чтобы преобразовать изображение в код, вы можете просто ввести вручную код, который вы видите на изображении. Если вы видите там какие-то символы, отличные от ASCII, вы можете изобрести что-нибудь другое, чтобы использовать вместо этого символа, и объясните это в комментариях. :)

Will Ness 18.12.2018 07:35

@WillNess FYI. Когда мне нужно вставить в документ специальные символы, а редактор не поддерживает опцию расширенного поиска символов, я использую Shapecatcher. С его помощью вы рисуете символ, а затем он возвращает вам символ, имя и даже код Unicode для него. Как только вы воспользуетесь им несколько раз, вы больше не боитесь использовать специальные уставы, только плохие редакторы. Приятно то, что как только вы часто находите нужный персонаж, это просто вырезание и вставка, чтобы вставить его в свой документ.

Guy Coder 18.12.2018 22:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
328
1

Ответы 1

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

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

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

В приложении / 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].

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

?- 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, который в Прологе более известен как обратный / 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 делают тот.


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

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

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

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

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

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


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

There are some replacements from letters to numbers and theta symbol that make me hard to understand.

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

Строки 1-4 - это снова заявленный исходный код.

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

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

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

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

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

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

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

Мой учитель попросил меня представить мое упражнение как второе изображение, которое я опубликовал. И есть некоторые шаги, которые я не понимаю.

Mai Hoàng Nam 17.12.2018 17:21

@ MaiHoàngNam Обычно я прошу вас задать другой вопрос, так как в StackOverflow вы задаете вопрос и получаете ответ. Это не должно превращаться в обсуждения. Я помогу вам понять одну или две конкретные вещи, но если вы спросите многих, я потребую, чтобы вы начали новый пост (вопрос).

Guy Coder 17.12.2018 17:24

@ MaiHoàngNam Какой конкретный шаг вы не понимаете?

Guy Coder 17.12.2018 17:25

Есть некоторые замены букв на числа и тета-символ, из-за которых мне трудно понять, что имел в виду мой учитель.

Mai Hoàng Nam 17.12.2018 17:25

Он старый учитель, и он учит нас делать домашние задания по старому методу.

Mai Hoàng Nam 17.12.2018 17:26

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

Mai Hoàng Nam 17.12.2018 17:28
There are some replacements from letters to numbers and theta symbol that make me hard to understand Я добавлю к ответу. Это займет несколько минут.
Guy Coder 17.12.2018 17:28

Да, я думаю, что вы профессор Prolog xD, и вы очень дружны с новым участником.

Mai Hoàng Nam 17.12.2018 17:31

Мой вызов учителя ------ обратный отрицателен обратному, RES (5, 2) представлен для соединения шагов 5 и 2.

Mai Hoàng Nam 17.12.2018 18:00

Я говорю об инверсии с линией на голове, которую вы захватили.

Mai Hoàng Nam 17.12.2018 18:04

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

Mai Hoàng Nam 17.12.2018 18:59

Мой учитель сказал нам понимать, что делает компьютер с Prolog, а не как работает программа.

Mai Hoàng Nam 17.12.2018 19:01

@ MaiHoàngNam Я закончил с моим ответом. Надеюсь, мне никогда больше не придется смотреть на трассировку, сделанную в этом формате.

Guy Coder 18.12.2018 22:28

Я понимал, как работает Пролог, но мой учитель математики заставил нас решать его с помощью математической терминологии. К счастью, мне удалось решить эту проблему с помощью разрешения «отрицательного предложения» (мой учитель назвал это так). Мой учитель хотел, чтобы ученики поняли, как машина работает с Прологом, но в форме отрицательного доказательства (вверху) это немного противоположно тому, что вы мне объяснили. XD

Mai Hoàng Nam 26.12.2018 04:16

Другие вопросы по теме